Flask Blogging Using External Files

Storing html, image, etc., not in static or templates folder



My typical production server folder structure looks like this


Graphical user interface, text

Description automatically generated


In the image above, applications  gets repo’ed in github. Posts will be updated only on the production machine. My code gets updated on my home machine. Therefore when I push an update the contents of applications/personalWebsite will be updated with the repo and all the posts since the last update will be erased/lost/whathaveyou by the git refresh. By having all my production data (i.e. database, posts templates, images) in the database/personalWebsite folder, I can now refresh to my hearts desire and the production data is wholly unaffected.


The reason for this mixup I the post templates data. I’m not sure most people store their blogposts in html templates, but using word to convert to html has been a great way to do it and here is an article where I go into the framework.


Using External templates



Here is sample code to explain what I am doing.



import jinja2


Route to reach the template


def blog_article(post_id_name_string):


    templates_path_lists = [


        os.path.join(current_app.config.get('DB_ROOT'),"posts", post_id_name_string)



    templateLoader = jinja2.FileSystemLoader(searchpath=templates_path_lists)


    templateEnv = jinja2.Environment(loader=templateLoader)

    template = templateEnv.get_template("blog/view_post.html")

    template_layout = templateEnv.get_template("_layout.html")

    template_post_index = templateEnv.get_template("index.html")

    template_post_table = templateEnv.get_template("closuresInSwift.html")

    # template_post_image = templateEnv.get_template("handwaveEmoji.png")


    image_file = os.path.join(current_app.config.get('DB_ROOT'),"posts", post_id_name_string, "handwaveEmoji.png")



    return template.render(template_layout=template_layout, template_post_index=template_post_index, \

        template_post_table=template_post_table,  \

        url_for=url_for, get_flashed_messages=get_flashed_messages)



Step 1: get list of all directories I plan to pull html templates from

Step 2: create jinja2.FileSystemLoader object that takes the list of “templates” folders

Step 3: create template objects that use the jinja2.FileSystemLoader object and take in the path to the html template relative to any of the “templates” paths I entered in the list


Then to render the template form the route I use



Inside the render parentheses I can pass jinja arguments just like I would with render_template. I can even pass in other template objects and have them rendered within the routes parent template (“template” in code above).


External Static folders

To get images from a directory outside of the static folder I create a route that I can call from the template. The route uses send_from_directory() and the arguments I pass are the direcetory and file name. IN this case I have a directory where I am keeping all my posts. Inside each post there is directory for the posts themselves. There I’ll keep an html file that is called index and whatever else belongs to the post.



# Custom static data


def custom_static(post_id_name_string,filename):

    return send_from_directory(os.path.join(current_app.config.get('DB_ROOT'),"posts", post_id_name_string), filename)



From inside the jinja template /html file (or index.html, if we’re continuing with the example from above), I call an image like this with url_for() the route method and the arguments for the specific blogpost directory and file name I am using



Description automatically generated


One issue, I have not resolved yet, is I cannot put jinja syntax (i.e. double curly braces) anywhere in my posts, unless they are images. Hence image for code above.









The reason to do this is so that I can just move update the application without deleting the blog posts. I was keeping everything in the templates and static directories and then making sub directories for each post. But each time I push an update I’d either have to keep all the posts in the application repository or manually move things in and make sure the database matches. Now, I can keep the database and all the blogpost files together and independently make changes to the website.