Integrate Flask with MongoDB

Akurathi Sri Krishna Sagar
9 min readAug 9, 2021

Flask

Flask is a Python Web Framework. It is a Python library used for developing Web Applications.

MongoDB

MongoDB is an Opensource Cross-Platform Document-Oriented Database program. It uses JSON like documents to store the data. It’s a NoSQL Database with optional Schema.

First, Install the Flask python library with the command :

pip install flask
or
pip3 install flask

Next, Install the Flask-PyMongo library, (which bridges Flask and PyMongo library) with the command :

pip install Flask-PyMongo

Now, go to MongoDB Community Download | MongoDB and download the MongoDB software for your respective OS. I’ve downloaded for Windows.

After downloading, install it and open it. Click on the Connect Button to start a local MongoDB Instance :

Now Click on the CREATE DATABASE button and provide the Database name and Collection name (Collection is similar to a Table in SQL) and click Create Database button :

At present, there is no data inside the collection we created :

Now we can test a Write operation to the Database with the following Flask Code :

from flask import Flask
from flask_pymongo import PyMongo
app = Flask("MongoDB App")
app.config["MONGO_URI"] = "mongodb://localhost:27017/flask-mongo"
# Replace "flask-mongo" with the Database Name you created.
mongo_client = PyMongo(app)
db = mongo_client.db
# Replace "mycollection" with the collection name you created. The below function is used for adding a single document to collection :def add():
db.mycollection.insert_one(
{
"name": "sagar",
"tech": "mongo"
}
)
add()

Run the above python file and go to MongoDB and you can view the data you entered in the above function inside the collection :

Now I’m going to show you how to use MongoDB with the HTML forms and create a Login Portal which takes in the input username and password and stores them in MongoDB collection. The user has the facility to Update username, Update Password, Delete the user, which are CRUD operations of the Database. The usernames are unique.

First create a file app.py and the following blocks explain the content in it :

The following block of code helps us to make a connection with the mongodb Database. Finally, the variable “mycollection” holds the connection with the collection in a database in MongoDB. This variable is used to perform CRUD operations on MongoDB :

from logging import error
from flask import Flask, render_template, request
from flask_pymongo import PyMongo
app = Flask("MongoDB App")
app.config["MONGO_URI"] = "mongodb://localhost:27017/flask-mongo"
mongo_client = PyMongo(app)
mycollection = mongo_client.db.mycollection

Next, there is form() function which is the starting point of the WebApp. Any user must enter this route to go inside the WebApp further :

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

The output of form.html looks like this :

The <body> part of form.html :

<body>
<p id="error">{{ error }}</p>
<form action="/home" method="POST" id="form">
<h1>Login/SignUp</h1>
<br>
<input type="text" class="inputBox" placeholder="Enter Username" name="username" pattern="[a-zA-Z0-9_-]{6,25}" required title="Must be alphanumeric in 6-25 chars"> <br><br><br> <input type="password" class="inputBox" placeholder="Enter Password" name="password" pattern="[a-zA-Z0-9_-]{6,25}" required title="must be alphanumeric in 6-25 chars"> <br><br><br> <button type="submit" id="runBtn">Submit</button>
</form>
</body>

form.html takes the username and password as input from the user and submits it to the route : /home with POST method so that, username and password won’t be visible as the query strings. I’ve also set the constraints to the username and password with the help of Regex as you can see above. In the above code, {{ error }} is a variable in jinja syntax, whose value can be passed by various other html files.

I’ve defined the /home route in the app.py file as below :

@app.route("/home", methods = ["GET","POST"])
def home():
if request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
found = mycollection.find({
"username": username,
})
l = [i for i in found]
if len(l)==0 :
mycollection.insert_one(
{
"username": username,
"password": password
}
)
return render_template("home.html",text="Hi Newbie,",username=username)
elif len(l)==1 and l[0]["username"]==username and l[0]["password"]==password:
return render_template("home.html", text="Welcome Back,",username=username)
elif len(l)==1 and l[0]["username"]==username and l[0]["password"]!=password:
return render_template("form.html", error="Incorrect Password")

The form.html submits the username and password to the above function or the route. The above home() function does the following :

  • Get the username and password from the form.
  • Find if any document in MongoDB already exists with the same username.
  • If no username is found already, then, create a document in the MongoDB with the help of CollectionName.insert_one({data}) function and redirect the user to home.html file by passing the username and some text as arguments which we will catch in the home.html with the help of jinja syntax.
  • Else if, the username already exists in the MongoDB, and the username and password provided by user matches with the values previously in the database, then redirect the user to home.html by passing the username and text as arguments.
  • Else if, the username already exists in the MongoDB, but the password provided by the user doesn’t match the password present in the MongoDB, then keep the user in the form.html itself, without redirecting and pass the error argument to the form.html showing that the password is incorrect.

Now, I’m entering a username and password in the /form page :

And click the Submit button. As there are no users now, a new user will be created in MongoDB. Now, I’m in the /home route :

The <body> part of the above home.html :

It contains 2 <p> elements and 3 buttons for Update Username, Update Password and Delete User and they redirect the user to the /form2, /form4 and /delete routes respectively.

<body>
<div id="main">
<p id="text">{{ text }}</p>
<p id="text">{{ username }}</p>
<div id="mainDiv">
<form action="/form2">
<button type="submit" id="runBtn">Update Username</button>
</form>
<form action="/form4">
<button type="submit" id="runBtn">Update Password</button>
</form>
<form action="/delete">
<button type="submit" id="runBtn">Delete User</button>
</form>
</div>
</div>
</body>

A new document is created in MongoDB :

Now click on Update Username button. You will be directed to the following page :

Python code for the above /form2 route :

@app.route("/form2")
def form2():
return render_template("update_username.html")

<body> part of update_username.html :

<body>
<p id="error">{{ error }}</p>
<form action="/form3" method="POST" id="form">
<h1>Change Username</h1>
<br>
<input type="text" class="inputBox" placeholder="Enter old username" name="username" pattern="[a-zA-Z0-9_-]{6,25}" required title="Must be alphanumeric in 6-25 chars"> <br><br><br> <input type="password" class="inputBox" placeholder="Enter Password" name="password" pattern="[a-zA-Z0-9_-]{6,25}" required title="must be alphanumeric in 6-25 chars"> <br><br><br> <input type="text" class="inputBox" placeholder="Enter new username" name="new_username" pattern="[a-zA-Z0-9_-]{6,25}" required title="Must be alphanumeric in 6-25 chars"> <br><br><br> <button type="submit" id="runBtn">Submit</button>
</form>
</body>

update_username.html collects the already existing username and password and the new_username and submits them to /form3 route.

Now, I’m updating my username by providing the required details :

Click on Submit button. When you click on Submit button, you will be directed to /form3 route. The python code for /form3 :

@app.route("/form3", methods=["GET","POST"])
def form3():
if request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
new_username = request.form.get("new_username")
found = mycollection.find({
"username": username,
})
l = [i for i in found]
if len(l)==0 :
return render_template("update_username.html", error="Username not found!")
elif len(l)==1 and l[0]["username"]==username and l[0]["password"]==password:
mycollection.update_one(
{"username": username},
{"$set": {"username": new_username}}
)
return render_template("form.html", error="Username Updated")
elif len(l)==1 and l[0]["username"]==username and l[0]["password"]!=password:
return render_template("update_username.html", error="Incorrect Password")

The above python code checks the old username and password. If both of them are correct and the new username matches the constraints, then the username will be updated in the MongoDB with the help of .update_one({find}, {replace}) function and you will be directed to form.html again to login with the new credentials.

I’ve submitted my new username. It’s saying “username updated” at the top :

REFRESH the MongoDB also :

In the /home route, if you click Update Password, you will be directed to the /form4 route. Python code for /form4 :

@app.route("/form4")
def form4():
return render_template("update_password.html")

<body> part of update_password.html :

<body>
<p id="error">{{ error }}</p>
<form action="/form5" method="POST" id="form">
<h1>Change Password</h1>
<br>
<input type="text" class="inputBox" placeholder="Enter username" name="username" pattern="[a-zA-Z0-9_-]{6,25}" required title="Must be alphanumeric in 6-25 chars"> <br><br><br> <input type="password" class="inputBox" placeholder="Enter old password" name="password" pattern="[a-zA-Z0-9_-]{6,25}" required title="must be alphanumeric in 6-25 chars"> <br><br><br> <input type="password" class="inputBox" placeholder="Enter new password" name="new_password" pattern="[a-zA-Z0-9_-]{6,25}" required title="Must be alphanumeric in 6-25 chars"> <br><br><br> <button type="submit" id="runBtn">Submit</button>
</form>
</body>

The above file takes the username, old password and the new password and submits them to /form5 for validation.

Python Code for /form5 route :

@app.route("/form5", methods=["GET","POST"])
def form5():
if request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
new_password = request.form.get("new_password")
found = mycollection.find({
"username": username,
})
l = [i for i in found]
if len(l)==0 :
return render_template("update_password.html", error="Username not found!")
elif len(l)==1 and l[0]["username"]==username and l[0]["password"]==password:
mycollection.update_one(
{"username": username},
{"$set": {"password": new_password}}
)
return render_template("form.html", error="Password Updated")
elif len(l)==1 and l[0]["username"]==username and l[0]["password"]!=password:
return render_template("update_password.html", error="Incorrect Password")

I’m providing the following details :

Click on Submit button and view the MongoDB database (password will change) :

Finally, we have a Delete User button in the /home route. When you click on that button, you will be directed to /delete route.

Python code for /delete :

@app.route("/delete")
def delete():
return render_template("delete_user.html", error="Provide the Crendentials")

<body> part of delete_user.html :

<body>
<p id="error">{{ error }}</p>
<form action="/form6" method="POST" id="form">
<h1>Login</h1>
<br>
<input type="text" class="inputBox" placeholder="Enter Username" name="username" pattern="[a-zA-Z0-9_-]{6,25}" required title="Must be alphanumeric in 6-25 chars"> <br><br><br> <input type="password" class="inputBox" placeholder="Enter Password" name="password" pattern="[a-zA-Z0-9_-]{6,25}" required title="must be alphanumeric in 6-25 chars"> <br><br><br> <button type="submit" id="runBtn">Submit</button>
</form>
</body>

The delete_user.html takes the already existing username and password and submits them to /form6 route.

Python code for /form6 :

@app.route("/form6", methods=["GET","POST"])
def form6():
if request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
found = mycollection.find({
"username": username,
})
l = [i for i in found]
if len(l)==0 :
return render_template("delete_user.html", error="Username not found!")
elif len(l)==1 and l[0]["username"]==username and l[0]["password"]==password:
mycollection.delete_one({
"username": username
})
return render_template("form.html", error="User Deleted")
elif len(l)==1 and l[0]["username"]==username and l[0]["password"]!=password:
return render_template("delete_user.html", error="Incorrect Password")

If the username and password matches, then that user document in MongoDB will be deleted with the help of .delete_one({data}) function.

After providing the username and password for deletion, click on Submit button. Check the MongoDB, and you can see that the document will be deleted.

In the app.py file, finally add the following line of code to start the server :

app.run(host="", port=1234)
# You can provide any non occupied port number.

GitHub Link for the Code :

asks1012/flask_mongoDB (github.com)

In this article, I’ve discussed the CRUD operations on MongoDB with the help of Flask Framework.

Thanks for Reading 😊

--

--