Introduction
This article is a part of a 30 day Python challenge series. You can find the links to all the previous posts of this series here:
- 30 Days of Python 👨💻 - Day One - Introduction
- 30 Days Of Python 👨💻 - Day 2 - Data Types I
- 30 Days of Python 👨💻 - Day 3 - Data Types II
- 30 Days Of Python 👨💻 - Day 4 - Data Types III
- 30 Days Of Python 👨💻 - Day 5 - Conditions And Loops I
- 30 Days Of Python 👨💻 - Day 6 - Loops II And Functions
- 30 Days Of Python 👨💻 - Day 7 - Developer Environment
- 30 Days Of Python 👨💻 - Day 8 - OOP Basics
- 30 Days Of Python 👨💻 - Day 9 - OOP Pillars
- 30 Days Of Python 👨💻 - Day 10 - OOP Missing Pieces
- 30 Days Of Python 👨💻 - Day 11 - Functional Programming
- 30 Days Of Python 👨💻 - Day 12 - Lambda Expression And Comprehensions
- 30 Days Of Python 👨💻 - Day 13 - Decorators
- 30 Days Of Python 👨💻 - Day 14 - Handling Errors
- 30 Days Of Python 👨💻 - Day 15 - Generators
- 30 Days Of Python 👨💻 - Day 16 - Module Basics
- 30 Days Of Python 👨💻 - Day 17 - External Modules
- 30 Days of Python 👨💻 - Day 18 - File I/O
- 30 Days Of Python 👨💻 - Day 19 - Regular Expressions
- 30 Days Of Python 👨💻 - Day 20 - Debugging And Testing
- 30 Days Of Python 👨💻 - Day 21 - Scripting Basics
- 30 Days of Python 👨💻 - Day 22 - Scripting Extras
- 30 Days Of Python 👨💻 - Day 23 - Web Scraping
- 30 Days Of Python 👨💻 - Day 24 - Web Development Basics
Starting from the basic skeleton of the Flask app, today I implemented some basic features to complete our simple minimalist blog application. First using Flask’s template inheritance pattern, I worked on re-using common template code and then added two dummy posts to render them dynamically. Finally, generating a requirements.txt file to store all the package dependencies in a single file which can then be used to download all the packages using a single command.
Template Inheritance
Currently, the index.html, about.html templates contain duplicate HTML code. Since Flask uses Jinja as the templating engine, we can use the powerful template inheritance concept to create a base template file which would contain all the common HTML code such as the HTML skeleton, navbar, footer, etc. Other templates can then extend this base template hence making our template code more reusable. I created a base template file layout.html to contain the common template structure as follows:
layout.html
- {% extends "layout.html" %}
- {% block title %}Index{% endblock %}
- {% block head %}
- {{ super() }}
- <style type="text/css">
- .important { color: #336699; }
- </style>
- {% endblock %}
- {% block content %}
- <h1>About</h1>
- <p class="important">
- Hi. I am Arindam. I love building User Interfaces. I am currently learning
- Python and created this simple blog using the Flask web development
- framework.
- {% endblock %}
A template re-usable block can be created and the code for that block needs to be placed within {% block block_name %} {% endblock %} The {% block %} informs the template engine that a child template may override these portions of the template.
The other files can then inherit this base template like this:
about.html
- {% extends "layout.html" %}
- {% block title %}Index{% endblock %}
- {% block head %}
- {{ super() }}
- <style type="text/css">
- .important { color: #336699; }
- </style>
- {% endblock %}
- {% block content %}
- <h1>About</h1>
- <p class="important">
- Hi. I am Arindam. I love building User Interfaces. I am currently learning
- Python and created this simple blog using the Flask web development
- framework.
- {% endblock %}
Here, the super() is used to render the contents of a block defined in the parent template.
More on templating using Flask can be found here https://flask.palletsprojects.com/en/1.1.x/patterns/templateinheritance/
Creating a Page Not Found Route
In Flask, we can handle various exceptions that can happen while loading the contents from the server such showing a custom 404 page when a route is not found, showing a custom page when there is a 500 internal server error, etc. I created a simple not_found.html file that would be rendered when a route is not found.
not_found.html
- {% extends 'layout.html' %}
- {% block title %}Page Not Found{% endblock %}
- {% block content %}
- <h1>Page Not Found</h1>
- <p class="important">
- Sorry, this page does not exist!
- {% endblock %}
server.py
- @app.errorhandler(404)
- def page_not_found(error):
- return render_template('not_found.html'), 404
More on Flask error handling can be found here.
Adding Sample Posts
For simplicity, I created a posts folder inside the templates directory and created two dummy post files first-post.html and second-post.html. Then I created a [posts.py](http://posts.py) file to read all the post files and store the names of the files in a list that can be rendered on the home page.
posts.py
- import os
- def get_all_post_names():
- try:
- post_files = os.listdir('templates/posts')
- post_names = list(map(lambda x: x.split('.')[0], post_files))
- return post_names
- except:
- print('An error occurred while fetching posts')
- return []
- {% extends "layout.html" %}
- {% block title %}Index{% endblock %}
- {% block head%}
- {{ super() }}
- {% endblock %}
- {% block content %}
- <h1 class="title">
- Welcome to the Python Blog.
- </h1>
- <h2>Recent Posts</h2>
- <ul class="post-list">
- {% for post in post_names %}
- <li><a href="posts/{{post}}.html">{{post}}</a></li>
- {% endfor %}
- </ul>
- {% endblock %}
All Python statements are written inside {% %} blocks as per the Jinja template syntax. Dynamic values are placed with {{ }}. We should now be able to see the two posts on the home page. Now on clicking on a post, it should open the respective post page. For that, we have to create a route that handles the post pages dynamically.
- @app.route('/posts/<string:post_name>')
- def show_post(post_name):
- return render_template(f'posts/{post_name}.html')
This route will handle page names and render the respective post pages dynamically.
Generating a requirement.txt file
In our Python project, we can use several external packages. If we want to share this project with someone, we need to share all the project files and also mention all the packages that are required to run the project along with the correct version number. This is not quite a practical approach.
All the installed dependencies used in the project can be listed in a single requirements.txt file (as per convention) along with their version using this command.
$ pip freeze > requirements.txt
This generates the requirements.txt file for the project. This file can be uploaded to any GIT repository. When someone downloads the project, they just need to run pip install -r requirement.txt, and all the project related dependencies would be installed with the exact versions automatically.
The complete project code can be found here.
References
The above project is a very minute use case of creating web apps using Python. I would like to list some useful references for further exploration:
- A great Python web development course from edX
- Building REST APIs using Flask
- REST api using Django
- https://programminghistorian.org/en/lessons/creating-apis-with-python-and-flask
- Using Flask with Angular
- Using Flask with React
- Django and Angular app
That’s all for today. For the remaining part of this series, I will be briefly exploring advanced topics such as the basics of Machine Learning and Data Science with Python.
Have a great one!

Join the conversation! Your thoughts help the community grow.