Steps to Create Python Web App | Python Flask Example


Flask, Python

In this tutorial we will cover the following topics:

  • Introduction to Flask
  • Creating a Virtual Environment with Python 3
  • Installing Flask packages with pip
  • Create a simple Flask Python Web App blog
  • Setting up a sqlite3 database to save our blog posts
  • Creating a simple crud interface.

 

What is flask

  • Flask is a lightweight python framework for web development that provides the basic tools that a developer would need to develop a fully functioning website. It gives the developer more freedom than other frameworks as it does not enforce a certain type of work flow.
  • Flask is easy to set up and getting an app up and running with it takes no time.
  • Flask comes with a development server which makes it easy to debug the web app. It also comes with a template engine called jinja2.
  • Flask has built in objects such as a request object and a session object, most of which will be used in this article where we will walk you through the process of creating a simple blog web app using flask and a sqlite3 database.

 

Lab environment:

Before getting started I would like to let let you know the environment that I work in:

  • Operating system: CentOS 8 Linux distro
  • Python version: 3.8.10
  • Code editor: VS code
  • Browser: Firefox 89.0.2

 

Step 1: Create Virtual Environment with Python3

Flask can be simply installed using pip/pip3 or easy_install globally, but it's preferable to set up an application environment using. This prevents the global Python installation from being affected by a custom installation, as it creates a separate environment for the application. The virtual environment manages this in separate environments and does not let the libraries of different versions overwrite each other.

In this command we are creating our virtual environment , we are going to name it blog-venv.

~]# python3 -m venv blog-venv

~]# ls -l blog-venv/
total 16
drwxr-xr-x 2 root root 4096 Jul 8 08:48 bin
drwxr-xr-x 2 root root 4096 Jul 8 08:48 include
drwxr-xr-x 3 root root 4096 Jul 8 08:48 lib
lrwxrwxrwx 1 root root 3 Jul 8 08:48 lib64 -> lib
-rw-r--r-- 1 root root 69 Jul 8 08:48 pyvenv.cfg

After running the  above command, you will notice that a directory named blog-venv was created, this directory contains the script that would activate the virtual environment,  let's activate the virtual environment:

~]# source blog-venv/bin/activate

After you activate the venv, your command prompt should look something like this:

(blog-venv) [root@server-1 ~]#

Notice the (blog-venv) at the beginning of the prompt. If you face any problems, please refer to the python docs.

To exit the virtual environment you can use deactivate command:

(blog-venv) [root@server-1 ~]# deactivate
[root@server-1 ~]#

 

Step 2: Installing Flask

Now you are ready to install the flask package using the following command:

(blog-venv) [root@server-1 ~]# pip3 install Flask

This will activate our environment and install Flask inside it. Now, we can create blog with Flask within this virtual environment, without affecting any other Python environment.

We will create a new directory to store all our flask blog related files:

(blog-venv) [root@server-1 ~]# mkdir flask-blog && cd flask-blog/

 

Step 3: Create your first flask python web application

Now since Flask is successfully installed, we will create our first python web application using flask. We will start by creating a python file and naming it "app.py":

from flask import Flask

app = Flask(__name__)

@app.route("/")
def main():
    return "Blog web app"
            
if __name__ == "__main__":
    app.run(debug=True)

Lets break down the above bit of code.

  • Line number 1: we imported the Flask class.
  • Line number 3: we created an instance of this class called app and give it the special variable __name__ as an argument. You need this because flask sets up the static folder paths behind the scenes.
  • Line number 5: we used the route() decorator to specify the URL that should launch our function.
  • Finally we used an if statement to see whether our module is imported by another application or is it ran directly, in case the module is ran directly and the flask development server will run on port 5000. The debug=true keyword argument adds more verbosity when displaying errors to make debugging easier.

Now let's run the flask web app:

(blog-venv) [root@server-1 flask-blog]# python3.8 app.py 
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 743-919-156

You flask blog is up and running, if you open your browser and visit the URL 127.0.0.1:5000/ you will be greeted with this page:

Steps to Create Python Web App | Python Flask Example

At this point, you have a basic web app that displays the text "Blog web app", now is time to add some HTML to your web app.

 

Step 4: Using Flask templates

Using flask render_template()

In order to display HTML files using flask, you will need to use the render_template() function, it only takes the name of the HTML file and the variable that you would like to pass to the template engine if any (We will discuss the variables later in this article).

Since our main terminal is running the flask blog app, we will open another terminal and activate our virtual environment. Next let us update the code of app.py to use render_template():

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def main():
    return render_template("index.html")
        
if __name__ == "__main__":
    app.run(debug=True)

We imported the render_template() function and used it. Now the main() view function returns the result of the render_template function.

We gave render_template() function the name of the HTML file index.html as an argument. By default flask looks for the template files in the templates directory, so now we need to create a templates directory in the same directory as our app, and then create a file named index.html inside this templates directory.

Move to the directory in which your flask app is and enter this command:

(blog-venv) [root@server-1 flask-blog]# mkdir templates && touch templates/index.html

At this point, our directory structure should look like this:

.
├── app.py
└── templates
    └── index.html

1 directory, 2 files

We will place some dummy HTML data inside our index.html file as below:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
</head>
<body>
        <h1>Flask Blog app</h1>
</body>
</html>

Save the file and refresh your browser and visit 127.0.0.1:5000/, you should find your HTML file:

Steps to Create Python Web App | Python Flask Example

NOTE:
When debug is set to true, the flask development server will notice the changes in code, so you don't need to rerun the server after you modify the code, just refresh the page.
 * Detected change in '/root/app.py', reloading
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 743-919-156

 

Using jinja2 templates

There are two ways to style HTML in flask, the first one would be adding the CSS in the <style> tag and the javascript in the <script> tag and keeping everything in the same HTML file. But this would be inefficient in case you have multiple HTML templates and you want to change the CSS in all of them, you will need to change the CSS in each HTML file one at a time.

The second and more efficient way that utilizes the jinja2 template engine would be by creating separate CSS and javascript files and then linking them to your base HTML file and overriding only specific parts of the base file, this will be way more clear once you see an example. Lets create our base HTML file, we will call it base.html:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{% block title %} {% endblock %}</title>
        <link rel="stylesheet", href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
      {% block body %} {% endblock %}
</body>

 

Here we linked  CSS file to base.html file using the url_for() method that comes with flask, the url_for() method looks for the static files in a directory called static, it should be in the same level as the flask app and the templates directory. Navigate to your app directory,  and create a directory called static and inside it, a file named style.css:

(blog-venv) [root@server-1 flask-blog]# mkdir static && touch static/style.css

At this point, your directory structure should look like this:

 .
├── app.py
├── blog-venv
│ └── .....
├── static
│    └── style.css
└── templates
        ├── base.html
        └── index.html

Now we will place following CSS selectors in our style.css file:

body
{
    background-color: #8A2BE2;
}

.main-container
{
    background-color: white;
    color: black;
    border-radius: 10px;
    width: 70%;
    margin: auto;
    margin-top: 10%;
    padding: 5px;
    padding-left: 10px;
}

 

Displaying dynamic data in our template

Now lets talk about {% block title %},  {% block body %} and  {% endblock %} .These are just placeholders for the actual content that you want to display in the HTML page, they will be overridden with your content and the content will be displayed exactly where you placed them, here is an example, lets create a file called posts.html and make it inherit from base.html, this file will later display all of our blog posts

{% extends 'base.html' %}
{% block title %} Posts {% endblock %}
{% block body %}
        <div class="main-container">
                         <h1>First post</h1>
                         <div> posted on: 5th of june</div>
                         <div>this is  the first blog post</div>
                         <hr>
       </div>
{% endblock %}

 

We start by extending base.html, this tells jinja2 to add all the HTML code before, after and between the placeholder, this includes the CSS and javascript links, so all the styling in the style.css file is applied to this file as well.

Now let's add an endpoint called /posts to our flask app that returns the posts.html file that we just created:

from flask import Flask, render_template

app = Flask(__name__)


@app.route("/")
def main():
    return render_template("index.html")

@app.route("/posts")
def display_posts():
        return render_template("posts.html",)

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

 

Once you visit 127.0.0.1:5000/posts, posts.html should be returned, here is how my posts.html looks like:

Steps to Create Python Web App | Python Flask Example

 

Step 5: Setup Sqlite3 database for Python Web App

Before creating posts, we need to set up our database, flask allows you to use any kind of database any way you want, if you want to communicate with the database directly you can do so, if you want to use an object relational mapper (ORM) then you can install <a href="https://www.golinuxcloud.com/flask-sqlalchemy/" title="Flask SQLAlchemy [In-Depth Tutorial]" target="_blank" rel="noopener noreferrer">flask-sqlalchemy</a> which is one of the best ORMs out there. In this tutorial we will use the sqlite3 database, and we will communicate directly with it:

from flask import Flask, render_template
import sqlite3
import os

if  "mydb.db" not in os.listdir():

        conn = sqlite3.connect("mydb.db")
        db = conn.cursor()

        db.execute("CREATE TABLE posts (title TEXT, content TEXT, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)")
        conn.commit()
        conn.close()

app = Flask(__name__)

@app.route("/")
def main():
        return render_template("index.html")

@app.route("/posts")
def display_posts():
        return render_template("posts.html")

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

Let's break down the code snippet above,

Firstly, we imported sqlite3, which is the sqlite3 API for python, and then we used an if statement to check whether the database already exists, if it doesn't then we create a database called "mydb.db" first and secondly we connect to it and create a table inside called posts that has three fields, the first one is the title of the post, the second one is the content of the post, its name is content, and the third one is the time in which the post was created and it defaults to the time of the post creation, so there will be no need to manually fill it every time a post is created, finally we commit the changes and close the connection with the database.

 

Step 6: Create CRUD interface for Flask Blog

CRUD stands for Create, Read, Update and Delete, these are the four basic operations of a persistent storage, and now we will perform them on our blog posts. Until now, there no way to create a post other than connecting to the sqlite3 database and adding one manually, so let's add a way to add a post from the web app itself.

We are going to create an endpoint called /create_post, it is going to contain a form that consists of two fields, a title field and a content field, when a user fills the form, we will take the data in the filled form and save it to our sqlite3 database to later display them in the /posts endpoint.

 

Creating posts

Lets start by creating the HTML form, we will name the HTML file create.html (Remember that all HTML files should be in the templates directory):

{% extends 'base.html' %}

{% block title %} Create Post {% endblock %}

{% block body %}
    <div style="text-align: center;" class="main-container">
        <form method="POST">
            Title: <input type="text"name="title">
            <hr>
            Content:
            <br>
            <textarea name="content"></textarea>
            <hr>
            <button type="sumbmit">
            POST
            </button>
        </form>
    </div>
{% endblock %}

 

Now let's create the flask endpoint to create post:

from flask import request, Flask, render_template, url_for, flash, redirect   # Import these flask functions
import sqlite3
import os


if  "mydb.db" not in os.listdir():
        conn = sqlite3.connect("mydb.db")
        db = conn.cursor()
        db.execute("CREATE TABLE posts (title TEXT, content TEXT, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)")
        conn.commit()
        conn.close()

app = Flask(__name__)


@app.route('/create', methods=["GET", "POST"]) # Allowing Post requests

def create_post():
    if request.method.upper() == "POST":
        title = request.form.get("title")
        content = request.form.get("content")
        conn = sqlite3.connect("mydb.db")
        cur = conn.cursor()
        # Adding the post to the database
        cur.execute("INSERT INTO posts (title, content) VALUES(?, ?)", (title, content))
        conn.commit()
        cur.close()
        conn.close()
        return redirect(url_for("display_posts")) # redirect user
    return render_template("create.html")

@app.route("/")
def main():
        return render_template("index.html")

@app.route("/posts")
def display_posts():
        return render_template("posts.html")

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

The create_post() function checks if the method of the request is post request and if so, it takes the data from the field and saves them to the sqlite3 database and then redirects the use to the /posts endpoint where all the posts are displayed, if the fields of the form are empty, then we flash a message to let the user know that all the fields of the form should be filled. The date field is filled automatically.

 

Now if you visit 127.0.0.1:5000/create:

Steps to Create Python Web App | Python Flask Example

 

We will create a dummy post with some test Title and dummy data as content.

Steps to Create Python Web App | Python Flask Example

 

Display Flask messages

Now lets add the ability to display messages to base.html based on field's value. Here we will make sure all the provided fields are mandatory and if any field is left empty then the blog will display a message.

We will update our base.html to print flask message:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{% block title %} {% endblock %}</title>
        <link rel="stylesheet", href="{{ url_for('static', filename='style.css') }}">
</head>
<body>

      {% with messages = get_flashed_messages() %}
      {% if messages %}
       <div class=flashes>
         {% for message in messages %}
         <h2>{{ message }}</h2>
         {% endfor %}
      </div>
      {% endif %}
      {% endwith %}

      {% block body %} {% endblock %}
</body>

The {% with %} and {% for %} along with {% if %} are control structures offered by jinja2 to facilitate the control flow of the program and add support from the front-end.

 

Next we update our create_post() function in app.py to check for TITLE and CONTENT field. If any of the field is left empty then we will use flask message to print a message on the screen:

from flask import request, Flask, render_template, redirect   # Import these flask functions
import sqlite3
import os
from flask.helpers import flash, url_for

if  "mydb.db" not in os.listdir():
        conn = sqlite3.connect("mydb.db")
        db = conn.cursor()
        db.execute("CREATE TABLE posts (title TEXT, content TEXT, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)")
        conn.commit()
        conn.close()

app = Flask(__name__)
app.config["SECRET_KEY"] = "secret key"

@app.route('/create', methods=["GET", "POST"]) # Allowing Post requests

def create_post():
    if request.method.upper() == "POST":
        title = request.form.get("title")
        content = request.form.get("content")

        if title == None or content == None or title.strip() == "" or content.strip() == "":
            # flashes a message to tell the user to fill all the fields
            flash("Please fill all the fields")
            return render_template("create.html")

        conn = sqlite3.connect("mydb.db")
        cur = conn.cursor()
        # Adding the post to the database
        cur.execute("INSERT INTO posts (title, content) VALUES(?, ?)", (title, content))
        conn.commit()
        cur.close()
        conn.close()
        return redirect(url_for("display_posts")) # redirect user
    return render_template("create.html")

@app.route("/")
def main():
        return render_template("index.html")

@app.route("/posts")
def display_posts():
        return render_template("posts.html")

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

 

Now try to click on "POST" without providing any value in TITLE or CONTENT field and you should get a flash message:

Steps to Create Python Web App | Python Flask Example

 

Displaying posts

Now let's display our posts in the /display endpoint of our app:

...
@app.route("/posts")
def display_posts():
        conn = sqlite3.connect("mydb.db")
        cur = conn.cursor()
        cur.execute("SELECT *, rowid FROM posts") # Getting all the posts from the sqlite3 database
        posts = cur.fetchall() # fetching all the posts from the database and assigning them to the posts variable

        cur.close()
        conn.close()
        return render_template("posts.html", posts=posts)  # Passing the posts variable ( which is a list ) to the front-end so that jinja2 can loop over it and display all the posts
...

Here we connected to the database and fetched all the posts from it. and put it in a normal python list (thanks to the cur.fetch() function), then we passed that list to  the jinja2 template engine to loop over it and display all the posts.

 

Now let's loop over the post's list that in the HTML file using jinja2 and render all the posts, let's open posts.html and modify it:

{% extends 'base.html' %}
{% block title %} Posts {% endblock %}

{% block body %}

<div class="main-container">
    {% for post in posts %}
        <h1>{{ post[0] }}</h1>
        <div> posted on:{{ post[2] }}</div>
        <div>{{ post[1] }}</div>
        <hr>
    {% endfor %}

</div>

{% endblock %}

 

Notice how we can access the members of the posts list that same way we would in a normal python list. Now all the posts that you create from the /create will be displayed in /posts.

Steps to Create Python Web App | Python Flask Example

 

Now let's display only one post when a user navigates to its id. Let's create the HTML file first, we will call it post.html:

{% extends 'base.html' %}
{% block title %} Posts {% endblock %}

{% block body %}

<div class="main-container">
    <h1>{{ post[0] }}</h1>
    <div> posted on:{{ post[2] }}</div>
    <div>{{ post[1] }}</div>
    <hr>
</div>

{% endblock %}

 

Now lets create the flask endpoint, we will call it /post/<int:post_id> where int:post_id is a placeholder for any number:

@app.route("/posts/<int:post_id>")
def display_post(post_id):
    conn = sqlite3.connect("mydb.db")
    cur = conn.cursor()
    post = cur.execute("SELECT * FROM posts WHERE rowid = ?", (str(post_id))).fetchone() # Notice the fetchone() fucntion

    return render_template("post.html", post=post, post_id=post_id)
When a post is created it gets its own ID automatically from sqlite3, the first post has an ID of 1 and the second post 2, the third 3 etc. Now we are fetching the post with the ID that will be specified in the URL, and we will get only one post because there can only be one post with a given ID. When we were getting all the posts, we used the fetchall() function which returns a list with all the posts, now we are using the fetchone() function which returns only one post. not a list. We can also use the fetchall() function if we want, but it would return a list that contains only one post (the post with ID in the URL). So the difference is in the data structure that is returned to us, not in the items inside the data structure, the items in the data structure are determined by the ID. So we used fetchone() because it is more convenient when we are getting only one item not a list of items.

 

Now if you visit 127.0.0.1:5000/posts/5 , you will see only the fifth post.

Steps to Create Python Web App | Python Flask Example

 

Now instead of manually navigating through different posts, let's add a link to each post the leads to the post on its own from 127.0.0.1:5000/posts. Modify posts.html:

{% extends 'base.html' %}

{% block title %} Posts {% endblock %}

{% block body %}

<div class="main-container">
{% for post in posts %}
    <a style="text-decoration: none; color: black;"href="{{ url_for('display_post', post_id=post[3]) }}"><h1>{{ post[0] }}</h1></a>
    <div> posted on:{{ post[2] }}</div>

    <div>{{ post[1] }}</div>
    <hr>
{% endfor %}
</div>

{% endblock %}

 

Now you can click on any of the post from 127.0.0.1:5000/posts to access the respective post:

Steps to Create Python Web App | Python Flask Example

 

Deleting posts

Now we let's add the functionality to delete a post. this will only need an endpoint as there will be no need to create a template, we will only add a deletion button to each post.

from flask import request, Flask, render_template, redirect   # Import these flask functions
import sqlite3
import os
from flask.helpers import flash, url_for

if  "mydb.db" not in os.listdir():
        conn = sqlite3.connect("mydb.db")
        db = conn.cursor()
        db.execute("CREATE TABLE posts (title TEXT, content TEXT, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)")
        conn.commit()
        conn.close()

app = Flask(__name__)
app.config["SECRET_KEY"] = "secret key"

@app.route('/create', methods=["GET", "POST"]) # Allowing Post requests

def create_post():
    if request.method.upper() == "POST":
        title = request.form.get("title")
        content = request.form.get("content")

        if title == None or content == None or title.strip() == "" or content.strip() == "":
            # flashes a message to tell the user to fill all the fields
            flash("Please fill all the fields")
            return render_template("create.html")

        conn = sqlite3.connect("mydb.db")
        cur = conn.cursor()
        # Adding the post to the database
        cur.execute("INSERT INTO posts (title, content) VALUES(?, ?)", (title, content))
        conn.commit()
        cur.close()
        conn.close()
        return redirect(url_for("display_posts")) # redirect user
    return render_template("create.html")

@app.route("/")
def main():
        return render_template("index.html")

@app.route("/posts")
def display_posts():
        conn = sqlite3.connect("mydb.db")
        cur = conn.cursor()
        cur.execute("SELECT *, rowid FROM posts") # Getting all the posts from the sqlite3 database
        posts = cur.fetchall() # fetching all the posts from the database and assigning them to the posts variable
        cur.close()
        conn.close()
        return render_template("posts.html", posts=posts)  # Passing the posts variable ( which is a list ) to the front-end so that jinja2 can loop over it and display all the posts

@app.route("/posts/<int:post_id>")
def display_post(post_id):
    conn = sqlite3.connect("mydb.db")
    cur = conn.cursor()
    post = cur.execute("SELECT * FROM posts WHERE rowid = ?", (str(post_id))).fetchone() # Notice the fetchone() fucntion

    return render_template("post.html", post=post, post_id=post_id)

@app.route("/posts/<int:post_id>/delete")
def delete_post(post_id):
    conn = sqlite3.connect("mydb.db")
    cur = conn.cursor()
    cur.execute("DELETE FROM posts WHERE rowid = ?", (str(post_id)))
    conn.commit()

    return redirect(url_for("display_posts"))

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

 

We connect to the database like before, and then we use the DELETE statement, which is another SQL statement. Now lets add the deletion button in the post.html template:

{% extends 'base.html' %}
{% block title %} Posts {% endblock %}

{% block body %}

<div class="main-container">
    <h1>{{ post[0] }}</h1>
    <div> posted on:{{ post[2] }}</div>
    <div>{{ post[1] }}</div>
    <hr>
    <a style="text-decoration: none; color: red;" href="{{ url_for('delete_post', post_id=post_id) }}">DELETE</a>
</div>

{% endblock %}

 

Now if you visit 127.0.0.1:5000/posts/1 , you will see the post and the DELETE button:

Steps to Create Python Web App | Python Flask Example

 

Once you click on the DELETE button, the post will be deleted and you will be redirected to the posts page. Here we have deleted first post so now we only have 4 more posts:

Steps to Create Python Web App | Python Flask Example

 

Editing posts

Lastly we need to add a way to edit posts. This is going to be similar to creating posts, lets start by creating the flask endpoint, we will call it /posts/<int_id>/edit :

@app.route("/posts/<int:post_id>/edit", methods=["POST", "GET"])
def edit_post(post_id):
    conn = sqlite3.connect("mydb.db")
    cur = conn.cursor()
    post = cur.execute("SELECT * FROM posts WHERE rowid = ?", (str(post_id))).fetchone()

    if request.method.upper() == "POST":
        title = request.form.get("title")
        content = request.form.get("content")

        if title == None or content == None or title.strip() == "" or content.strip() == "":
            flash("Please fill all the fields")
            return render_template("edit.html", post=post)

        cur.execute("UPDATE posts SET title = ?, content = ? WHERE rowid = ?", (title, content, post_id))
        conn.commit()

        return redirect(url_for("display_posts"))

    return render_template("edit.html", post=post)

 

We connected to the database,  then we checked whether the request method is POST or GET, if the method is POST we get the data filled by the user in the form and then we use the UPDATE statement to overwrite the data saved in the sqlite3 database and save the newly added data. If the method is GET, then we return the edit.html template (in the templates directory) which we will create now:

{% extends 'base.html' %}

{% block title %} Create Post {% endblock %}

{% block body %}

<div style="text-align: center;" class="main-container">
    <form method="POST">
        Title: <input value={{ post[0] }} type="text" name="title">
       <hr>
       Content:
       <br>
       <textarea name="content">{{ post[1] }}</textarea>
       <hr>
       <button type="submit">
             POST
        </button>
    </form>
</div>

{% endblock %}

Here we used the value attribute in the <input> HTML tag to set the default value to be the current title of the post, and then we added the current value for the post content between the <textarea> HTML tag, we did this so that the user can edit the old values of the fields.

 

You can visit 127.0.0.1:5000/posts/2/edit and provide the updated Title and Content:
Steps to Create Python Web App | Python Flask Example

 

Once you click on POST, you will be redirected to 127.0.0.1:5000/posts where you can verify the updated Title and Content:

Steps to Create Python Web App | Python Flask Example

 

Conclusion

In this article, we walked through the whole life cycle of creating a python web app that allows user to create, edit and delete blog posts. We used flask for the back-end, jinja2 engine that comes with flask and sqlite3 as a database for our python web app, we used the sqlite3 python API to communicate with the database. You are now ready to create your own flask app.

 

References

sqlite3 tutorial
Flask docs

 

Related Searches: Python flask web page example, html to python flask, how to use flask python, create web app with python flask, flask tutorial python3, build web app with flask, flask application, flask web app tutorial, how to write web application in python, python web development using python, how to create web apps in python, web development using flask, simple web application using python, python flask step by step tutorial

Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

1 thought on “Steps to Create Python Web App | Python Flask Example”

  1. There’s a classic Python gotcha in the sqlite `cur.execute()` with the single rowid parameter. The `(str(post_id))` should be `(str(post_id), )` (note extra comma).

    This is Python, due to syntactic ambiguity, interprets `(foo)` as just `foo`, and when the sqlite3 api tries to resolve `str(post_id)` where post_id is 2 or more digits, it’ll see its length as >1, and complain that it got too many parameters for the single placeholder.

    Adding the trailing comma inside the tuple forces it to be a single-element tuple.

    Reply

Leave a Comment