Flask Web Framework

HARSHIL PARMAR
10 min readApr 16, 2022

--

Overview of Python Flask Framework

Web apps are developed to generate content based on retrieved data that changes based on a user’s interaction with the site. The server is responsible for querying, retrieving, and updating data. This makes web applications to be slower and more complicated to deploy than static websites for simple applications. There are two primary coding environments for the whole web app ecosystem. This article will give an overview of the Python Flask Framework and Its best practices.

Client-side Scripting

The code executed on the user’s browser visible to anyone who has access to the system, generating the first results.

Server-side Scripting

This type of code is run on the backend on a web server. To enable developers to design, build, maintain, host web apps over the internet, a web framework necessary.

What is Web Framework?

A web framework is an architecture containing tools, libraries, and functionalities suitable to build and maintain massive web projects using a fast and efficient approach. They are designed to streamline programs and promote code reuse. To create the server-side of the web application, you need to use a server-side language. Python is home to numerous such frameworks, famous among which are Django and Flask. Python Flask Framework is a lightweight micro-framework based on Werkzeug, Jinja2. It is called a micro framework because it aims to keep its core functionality small yet typically extensible to cover an array of small and large applications. Flask Framework depends on two external libraries: The Jinja2 template, Werkzeug WSGI toolkit. Even though we have a plethora of web apps at our disposal, Flask tends to be better suited due to -

  • Built-in development server, fast debugger.
  • Integrated support for unit testing.
  • RESTful request dispatching.
  • Jinja2 Templating.
  • Support for secure cookies.
  • Lightweight and modular design allows for a flexible framework.

What are the Critical elements of the Python Flask Framework?

Initialization: flask applications must create an application instance. The web server passes all the requests it receives from clients to objects for handling using a protocol for WSG from flask import Flask app = Flask (__name__) (An application instance is an object of class Flask.)

Routes and View Functions in Flask Framework Instance

Clients send requests to the webserver, in turn, sends them to the Flask application instance. The instance needs to know what code needs to run for each URL requested and map URLs to Python functions. The association between a URL and the function that handles it is called a route. The most convenient way to define a route in a Flask application is through the (app.route). Decorator exposed by the application instance, which registers the ‘decorated function,’ decorators are python feature that modifies the behavior of a function.

Deploying Python Flask Framework on Heroku Cloud

  • Install Heroku client and Foreman (to test simulated Heroku environment on pc).
  • Create an application using Heroku CLI and Git.
  • Add ‘procfile’ to the application using a gunicorn webserver run ‘ Heroku create <unique-app-name>-api-heroku’ in the application folder.
  • Push application to master branch https://git.heroku.com/kbucket-api-heroku.git , clone the repository, and push to heroku-master.
  • Note the app URL like (https://<unique-app-name>-api-heroku.herokuapp.com/ ). The application lives here. Heroku will assign the data that will garner to a PostgreSQL database.
  • One can also test the live API of the application, and if successfully deployed, it will return a 201 status code.

Some Code :

To continue, you must have Python and flask installed on your machine.

Now we will create our Python file to write the code, mine is named “app.py”. We must keep this file in a separate folder.

The following line imports the Flask class from the flask package

from flask import Flask

Now we will create an object of the Flask class which in this case is called “app”

app = Flask(__name__)

Here __name__ is a special variable whose value depends on how we execute the script(Python file).

Next Step is to create a route decorator which binds the value of the URL provided in the route to a function.

@app.route('/home')
def Welcome():
return "FlaskWebFramework"

In the above snippet, the route decorator links the ‘/home’ URL with the Welcome function. The Welcome function, in turn, returns the string value “FlaskWebFramework”.

Last Step is to make sure that we are running the script and not importing it and if we are running the script then we will run the app in Debug mode.

if __name__ == "__main__":
app.run(debug=True)

Note: It is not necessary to include the debug condition inside the run method of the app object But its use enables easy debugging.

source code:

from flask import Flask

app = Flask(__name__)

@app.route('/')
@app.route('/home')
@app.route('/FlaksWebFramework')
def Welcome():
return "FlaksWebFramework"

if __name__ == "__main__":
app.run(debug=True)

All the three URLs will show the same output which in our case is FlaskWebFramework.

Using templates- flask

In the previous section, we learnt how to create our first webpage and passed text to be displayed on those web pages by returning the values from the functions inside the route decorators, we can also return HTML code from these functions but that won’t be ideal so instead, we use what is called a template.

A template is a pre-designed webpage or set of HTML webpages that anyone can use to “plug-in” their text content and images into to create a website.

We can import the render_template function from the Flask library to make use of templates on our website.

The following code snippet shows the use of templates:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
@app.route('/home')
@app.route('/FlaskWebFrameWork')
def Welcome():
return render_template('index.html')

if __name__ == "__main__":
app.run(debug=True)

To render a template, we must first create it which can be done easily by creating an HTML file.

The HTML files must be stored in a separate folder called ‘templates’.

In the above snippet we rendered the index.html which contains the following code:

<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FlaskWebFramework Blog</title>
</head>

<body>
<h1>Welcome to FlaskWebFramework!</h1>
</body>

</html>

Creating a database model in flask

In this section, we will create a model for our database.

This database will be useful in providing CRUD functionality to our blogging website by handling the posts which will be made there.

Creating a model for our database makes easy handling of data possible.

We will use the ‘flask_sqlalchemy’ external library to handle the database operations.

The following snippet shows how to model our database:

class FlaskWebFramework(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False, unique=True)
content = db.Column(db.Text, nullable=False)
posted_by = db.Column(db.String(20), nullable=False, default='N/A')
posted_on = db.Column(db.DateTime, nullable=False, default=datetime.utcnow())

def __repr__(self):
return self.title

In the above snippet, we modeled our data but to make it work, we have to make some other adjustments and inclusions.

Here, the name of our model is FlaskWebFramework and it inherits from a predefined model. The attributes of the model are title, content, posted_by and posted_on. This provides us with the main information about the posts made on our blogging website.

Note: The __repr__ method returns a printable representation of the database object. In our case, this representation will be the title of the posts.

The following is the complete code for model creation:

from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///posts.db'
db = SQLAlchemy(app)


class CodeSpeedyBlog(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False, unique=True)
content = db.Column(db.Text, nullable=False)
posted_by = db.Column(db.String(20), nullable=False, default='N/A')
posted_on = db.Column(db.DateTime, nullable=False,
default=datetime.utcnow())

def __repr__(self):
return self.title


db.create_all()
db.session.commit()

@app.route('/')
@app.route('/home')
@app.route('/FlaksWebFramework')
def Welcome():
return render_template('index.html')

if __name__ == "__main__":
app.run(debug=True)

We have configured our app to use the SQLite database with the help of flask_sqlalchemy library and we have named our database posts.db and ‘SQLite‘ was used for the database management.

We have also created a database object called ‘db’ and have used the suitable SQL syntaxes for creating and committing the database.

Creating a new post- flask

In this section, we will define the routes and functions that are needed to create a new post on our website and will also create a template for our new post creation webpage. The name of the template is new_post.html and it must be added to the templates folder.

The following snippet shows the route decorator and the concerned functions along with the managing of database and templates accordingly.

@app.route('/posts/new', methods=['GET', 'POST'])
def new_post():
if request.method == 'POST':
post_title = request.form['title']
post_content = request.form['post']
post_author = request.form['author']
new_post = FlaskWebFrameworkBlog(title=post_title,
content=post_content, posted_by=post_author)
db.session.add(new_post)
db.session.commit()
return redirect('/posts')
else:
return render_template('new_post.html')

Note: ‘GET’ is the default method in routes but if you route to have methods like ‘POST’ then you have to add them to a list. Before using the redirect function it must be imported from flask module and the ‘posts’ route must also be created beforehand which we will be doing in the next section.

Important: A blog object will be created every time we create a new post and this object follows the FlaskWebFramework model.

The complete code until now is given below:

from flask import Flask, render_template, redirect
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///posts.db'
db = SQLAlchemy(app)


class FlaskWebFrameworkBlog(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False, unique=True)
content = db.Column(db.Text, nullable=False)
posted_by = db.Column(db.String(20), nullable=False, default='N/A')
posted_on = db.Column(db.DateTime, nullable=False,
default=datetime.utcnow())

def __repr__(self):
return self.title


db.create_all()
db.session.commit()

@app.route('/')
@app.route('/home')
@app.route('/FlaskWebFramework')
def Welcome():
return render_template('index.html')

@app.route('/posts/new', methods=['GET', 'POST'])
def new_post():
if request.method == 'POST':
post_title = request.form['title']
post_content = request.form['post']
post_author = request.form['author']
new_post = FlaskWebFrameworkBlog(title=post_title,
content=post_content, posted_by=post_author)
db.session.add(new_post)
db.session.commit()
return redirect('/posts')
else:
return render_template('new_post.html')

if __name__ == "__main__":
app.run(debug=True)

Remember we need to create a posts route for the above to work which we will be doing shortly.

The content of the ‘new_post.html’ template is shown below:

<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New Post</title>
</head>

<body>
<h1>New Post:</h1>
<hr>
<h2>New Post:</h2>
<form action="/posts" method="POST">
<label for="title">Title:</label>
<input class="form-control" type="text" name="title" id="title" placeholder="Enter Title"
aria-label="Enter Title">
<br>
<label for="content">Author:</label>
<input class="form-control" type="text" name="author" id="author" placeholder="Enter Author"
aria-label=" Enter Author">
<br>
<label for="post">Post:</label>
<textarea class="form-control" id="post" name="post" placeholder="Enter Content" aria-label=" Enter Content"
rows="3"></textarea>
<br>
<input type="submit" value="Post">
</form>
<hr>
</body>

</html>

Creating a route for reading posts in flask

In this section, we will create a route for reading the posts along with that we will also create the ‘posts.html’ template.

This will create a section in our webpage called Posts which will contain all the posts which have been posted on our platform.

Following is the code snippet for the above purpose:

@app.route('/posts',  methods=['GET', 'POST'])
def posts():
if request.method == 'POST':
post_title = request.form['title']
post_content = request.form['post']
post_author = request.form['author']
new_post = FlaskWebFrameworkBlog(title=post_title,
content=post_content, posted_by=post_author)
db.session.add(new_post)
db.session.commit()

return redirect('/posts')
else:
all_posts = FlaskWebFrameworkBlog.query.order_by(FlaksWebFramework.posted_on).all()
return render_template('posts.html', posts=all_posts)

The render template function takes an additional parameter of posts which will be used to display the added posts.

The contents of the ‘posts.html’ template are shown below:

<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>All Posts</title>
</head>

<body>
<br>
<div>
<h1 style="display: inline">All Posts Here: </h1>
<a style="display: inline" class="btn btn-success float-right" href="/posts/new">+ New Post</a>
</div>
<br>
<hr>
{% for post in posts%}
<h2>{{post.title}}</h2>

{% if post.author %}
<small>Written By {{post.posted_by}} on {{post.posted_on}}</small>
{% else%}
<small>Written by Anonymous on {{post.posted_on}}</small>
{% endif %}
<p style="white-space: pre-wrap">{{post.content}}</p>
<br>
<a href="/posts/delete/{{post.id}}"><img
src="https://qph.fs.quoracdn.net/main-qimg-83c6de25ed91d13a4f09fb5f11ca8853" height="50px" width="50px"></a>
<a href="/posts/edit/{{post.id}}"><img
src="https://www.2g-eng.com/wp-content/uploads/2016/01/design-engineering-icon-small.png" height="50px"
width="50px"></a>
<hr>
{% endfor %}

</body>

</html>

Note: Some Jinja2 syntax has been used in the above template to easily handle the post data.

Our ‘app.py’ file will look like this after the above changes.

from flask import Flask, render_template, redirect, request
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///posts.db'
db = SQLAlchemy(app)


class CodeSpeedyBlog(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False, unique=True)
content = db.Column(db.Text, nullable=False)
posted_by = db.Column(db.String(20), nullable=False, default='N/A')
posted_on = db.Column(db.DateTime, nullable=False,
default=datetime.utcnow())

def __repr__(self):
return self.title


db.create_all()
db.session.commit()

@app.route('/')
@app.route('/home')
@app.route('/FlaskWebFramework')
def Welcome():
return render_template('index.html')

@app.route('/posts', methods=['GET', 'POST'])
def posts():
if request.method == 'POST':
post_title = request.form['title']
post_content = request.form['post']
post_author = request.form['author']
new_post = FlaskWebFrameworkBlog(title=post_title,
content=post_content, posted_by=post_author)
db.session.add(new_post)
db.session.commit()

return redirect('/posts')
else:
all_posts = FlaskWebFrameworkBlog.query.order_by(FlaskWebFrameworkBlog.posted_on).all()
return render_template('posts.html', posts=all_posts)

@app.route('/posts/new', methods=['GET', 'POST'])
def new_post():
if request.method == 'POST':
post_title = request.form['title']
post_content = request.form['post']
post_author = request.form['author']
new_post = FlaskWebFrameworkBlog(title=post_title,
content=post_content, posted_by=post_author)
db.session.add(new_post)
db.session.commit()
return redirect('/posts')
else:
return render_template('new_post.html')

if __name__ == "__main__":
app.run(debug=True)

Running the ‘app.py’ file the localhost:5000

Creating an edit route

Now to add the update feature to our website, we will create the edit route so that we can update the already created posts.

The following snippet contains the edit route :

@app.route('/posts/edit/<int:id>', methods=['GET', 'POST'])
def edit(id):
to_edit = FlaskWebFrameworkBlog.query.get_or_404(id)
if request.method == 'POST':
to_edit.title = request.form['title']
to_edit.author = request.form['author']
to_edit.content = request.form['post']
db.session.commit()
return redirect('/posts')

else:
return render_template('edit.html', post=to_edit)

Note: We have used the ‘.get_or_404’ function to avoid crashing of our website in case the post is not found.

Now we will create the ‘edit.html’ template for our edit page which will contain the following;

<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Edit Post</title>
</head>


<body>
<h1>Editing Post: </h1>
<hr>
<h2>Edit:</h2>

<form action="/posts/edit/{{post.id}}" method="POST">
<label for="content">Title:</label>
<input class="form-control" type="text" name="title" id="title" value="{{post.title}}">
<br>
<label for="content">Author:</label>
<input class="form-control" type="text" name="author" id="author" value="{{post.posted_by}}">
<br>
<label for="post">Post:</label>
<textarea class="form-control" id="post" name="post" rows="3">{{post.content}}</textarea>
<br>
<input type="submit" value="Save">
</form>
<hr>
</body>

</html>

Creating a delete route

The last feature in our CRUD app will be to delete an existing post which is done in the following code snippet:

@app.route('/posts/delete/<int:id>')
def delete(id):
to_delete = FlaskWebFrameworkBlog.query.get_or_404(id)
db.session.delete(to_delete)
db.session.commit()
return redirect('/posts')

Note: We used the redirect function to go back to existing posts page after deleting one of them.

After following these steps our ‘app.py’ file will look like

from flask import Flask, render_template, redirect, request
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///posts.db'
db = SQLAlchemy(app)


class FlaskWebFrameworkBlog(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False, unique=True)
content = db.Column(db.Text, nullable=False)
posted_by = db.Column(db.String(20), nullable=False, default='N/A')
posted_on = db.Column(db.DateTime, nullable=False,
default=datetime.utcnow())

def __repr__(self):
return self.title


db.create_all()
db.session.commit()

@app.route('/')
@app.route('/home')
@app.route('/FlaskWebFramework')
def Welcome():
return render_template('index.html')

@app.route('/posts', methods=['GET', 'POST'])
def posts():
if request.method == 'POST':
post_title = request.form['title']
post_content = request.form['post']
post_author = request.form['author']
new_post = FlaskWebFrameworkBlog(title=post_title,
content=post_content, posted_by=post_author)
db.session.add(new_post)
db.session.commit()

return redirect('/posts')
else:
all_posts = FlaskWebFrameworkBlog.query.order_by(FlaskWebFrameworkBlog.posted_on).all()
return render_template('posts.html', posts=all_posts)

@app.route('/posts/delete/<int:id>')
def delete(id):
to_delete = FlaskWebFrameworkBlog.query.get_or_404(id)
db.session.delete(to_delete)
db.session.commit()
return redirect('/posts')

@app.route('/posts/edit/<int:id>', methods=['GET', 'POST'])
def edit(id):
to_edit = FlaskWebFrameworkBlog.query.get_or_404(id)
if request.method == 'POST':
to_edit.title = request.form['title']
to_edit.author = request.form['author']
to_edit.content = request.form['post']
db.session.commit()
return redirect('/posts')

else:
return render_template('edit.html', post=to_edit)

@app.route('/posts/new', methods=['GET', 'POST'])
def new_post():
if request.method == 'POST':
post_title = request.form['title']
post_content = request.form['post']
post_author = request.form['author']
new_post = FlaskWebFrameworkBlog(title=post_title,
content=post_content, posted_by=post_author)
db.session.add(new_post)
db.session.commit()
return redirect('/posts')
else:
return render_template('new_post.html')

if __name__ == "__main__":
app.run(debug=True)v

This is our final ‘app.py’ file

--

--