Python Website Full Tutorial — Flask, Authentication, Databases
As a beginner in web development, I knew that understanding databases and SQL would be crucial to building robust web applications. I started my journey by learning the basics of SQL and relational databases, practicing with various exercises and projects.
After gaining some experience, I decided to focus on MySQL. I was excited to apply my new skills to future projects.
At the end you will able to create it from sctrach.
Table of Contents
1.Creating a basic Flask app
2. Creating routes/views
3. Jinja templating language and HTML templates
4. Handling HTTP requests (POST, GET, etc.)
5. Implementing message flashing
6. Setting up Flask SQLAlchemy
7. Creating database models and foreign key relationships
8. Creating and logging in user accounts
9. Adding and deleting user notes
Creating a basic Flask app
i. To get started with Flask, you first need to install it. You can do this using pip, the Python package installer, by running the following command in your terminal:
pip install flask
ii. Create a Flask app file Next, create a new Python file for your Flask app. This file will contain the code for your Flask app. You can name this file whatever you want, but for this example, we’ll name it app.py
.
iii. Import Flask In your app.py
file, import the Flask module using the following code:
from flask import Flask
iv. Create an instance of the Flask class Create an instance of the Flask class by calling the Flask
constructor and passing in the name of your app. This code should be added to your app.py
file:
app = Flask(__name__)
v. Create a route by defining a function and adding the @app.route()
decorator above it. The decorator tells Flask what URL should trigger the func. For example, the following code defines a route for the root URL /
:
@app.route('/')
def index():
return 'Hello, World!'
vi. Run the app Finally, run the app by calling the run()
method on your app instance. This code should also be added to your app.py
file:
if __name__ == '__main__':
app.run()
And that’s it! You now have a basic Flask app up and running. Of course, we will customize app further by adding more routes, templates, and views.
Now we will start actual implementation of project.
It is important to use a different environment for Flask installation because it helps in keeping your system clean and organized. Flask, like any other application, has dependencies that need to be installed to make it run properly.
Overall, using a separate environment for Flask installation helps in making the development process smoother and more efficient by keeping the dependencies required by Flask isolated and easy to manage.
File descriptions:-
Flask web application is dir where our project is present
Website is name of application
— static (folder to save all static files)
— templates(will contains all html boiler plates)
— __init__.py(file where flask app is created and use as package)
— auth.py (file will have all authentication content)
— models.py (file will have database releated query and settings)
— views.py (file will generate webpage on searching url)
main.py (present outside this is starting point of our application which uses all content of __init__.py
Creating routes/views
In Flask, a route refers to a URL pattern that maps to a function in your Python code. When a user requests a URL, Flask uses the route to determine which function to call to handle the request and generate a response.
In above example we set http://localhost:5000/
in their browser, Flask will call the index()
function and return the string "Hello, World!" as the response.
Routes are a fundamental part of building Flask applications, as they allow you to define the URLs that your users will interact with and map them to the appropriate code to handle the requests. By understanding how routes work in Flask, you can build more complex and powerful web applications that respond to user input in a dynamic and flexible way.
Jinja templating language and HTML templates
When building a web application, it’s common to have a consistent layout for all pages. Rather than repeating the same HTML code for every page, we can use a templating engine to create a base template with reusable components. In Flask, the templating engine of choice is Jinja2.
Jinja2 is a modern and designer-friendly templating language for Python, modelled after Django’s templates. It is used to generate HTML or XML pages that can be served to clients. It is widely used in web frameworks such as Flask, Django.
In this template, we define a block named “title” that can be overridden by child templates. We also define a navigation bar with links to the Home, Login, and Sign Up pages. We then define another block named “content” that child templates can use to insert their specific content.
To create a child template that extends this base template, we use the {% extends %}
tag at the top of the file. We can then override the “title” and “content” blocks as needed.
You should try to customize the template as per your choice. To get better understanding of them.
Handling HTTP requests (POST, GET)
The main difference between the GET and POST methods is that GET requests are used to retrieve data, while POST requests are used to send data. The data sent using the POST method is usually hidden from the user and is not visible in the URL.
In Flask, the request
object is used to handle incoming HTTP requests from the client. It contains all the data that the client sends to the server, including form data, cookies, and headers.
It’s important to note that when using the request
object, we should always check the method of the request using request.method
to make sure we're handling the correct type of request. Additionally, we should always validate any user input and sanitize any data that will be stored in the database to prevent security vulnerabilities such as SQL injection.
Implementing message flashing
In Flask, flash is a built-in function that allows you to display a message to the user when a certain event occurs, such as a successful login or an error in form submission. The flash function stores the message in a temporary session that is available to the next request. It is useful in situations where you want to provide feedback to the user after an action has been performed.
In the case of the auth.py
file, the flash
function is being used to verify if the user has entered valid input for the email, first name, and passwords fields. If the input is invalid, an error message is flashed to the user. These messages are then displayed on the page using the get_flashed_messages
function in the base.html template.
The get_flashed_messages
function retrieves all the flashed messages, which are then looped over in the template using a for loop. The category of each message is checked (e.g. error or success) and a corresponding HTML element with the appropriate CSS classes is rendered. The message itself is then displayed within the element.
Overall, using flash messages in Flask is an effective way to provide feedback to the user and improve the user experience. It allows you to communicate important information to the user without cluttering the page or interrupting the user flow.
Setting up Flask SQLAlchemy
In a Flask web application, you can use SQLAlchemy to interact with databases. You can define a model class that represents a table in your database and use the Object-Relational Mapping (ORM) to insert, update, delete, and query the data in that table.
To use SQLAlchemy, you will first need to install it using pip. You can do this by running the following command in your terminal or command prompt:
pip install sqlalchemy
In this example, we define a User
class that inherits from db.Model
, which is a SQLAlchemy base class. We define several columns in the class, each of which maps to a column in the database table. The id
column is a primary key, which is required for each table. The email
column is unique and cannot be null, while the password
, first_name
columns are also required.
To create the database, you will need to call the create_all()
method on your SQLAlchemy instance and pass in your Flask app instance.
Creating database models and foreign key relationships
When designing a database in SQLAlchemy, it is important to create the appropriate models and establish relationships between them. In our case, we want to create a database for storing user details and user-generated notes. Here’s an example of how you might set up your database models:
The Note
model has columns for id
, userNote
, date
, and user_id
. The id
column is the primary key for the Note
model, and is used to uniquely identify each note. The userNote
column stores the actual text of the note. The date
column is used to store the date and time when the note was created, and is set to the current time by default. The user_id
column is the foreign key for the User
model, and is used to establish many to one relationship between the Note
and User
models.
The User
model has columns for id
, email
, password
, and first_name
. The id
column is the primary key for the User
model, and is used to uniquely identify each user. The email
column stores the user's email address, and is set to be unique so that each user has a unique email. The password
column stores the user's password. The first_name
column stores the user's first name.
The notes
attribute in the User
model is used to create a one-to-many relationship between the User
and Note
models. This means that each user can have many notes. The notes
attribute is created using the relationship
function from SQLAlchemy. The first argument to relationship
is the name of the related model (Note
in this case).
Run this command python main.py
and see an instance for database is created with name as database.db
Creating and logging in user accounts
In Flask, creating new user accounts and logging in users is an essential part of building web applications. The process involves capturing user information through a web form, validating the data, storing the data in a database, and providing access to protected content for authenticated users.
The login()
function handles both GET and POST requests sent to the /login
route. If the request method is POST, the email and password are extracted from the request's form data. The user's email is then used to search the database for a matching user record using the User.query.filter_by(email=email).first()
method. If a user with the given email is found, the hashed password is checked against the provided password using the check_password_hash
function. If the passwords match, a success message is flashed and the user is redirected to the home page using the redirect(url_for('views.home'))
function. If the passwords do not match, an error message is flashed. If the email is not found in the database, an error message is flashed.
The sign_up()
function also handles both GET and POST requests sent to the /sign-up
route. If the request method is POST, the email, first name, and passwords are extracted from the request's form data. The email is used to search the database for a matching user record using the User.query.filter_by(email=email).first()
method.
If a user with the given email already exists, an error message is flashed. Otherwise, a new user record is created with the email, first name, and hashed password using the generate_password_hash
function. If all the checks pass, a new user is created with the User
model and the generate_password_hash()
function from Flask-Bcrypt to hash the password for secure storage. The new user is then added to the database using db.session.add()
and committed using db.session.commit()
.
If the new user is successfully added to the database, a success message is flashed and the user is redirected to the homepage using the redirect()
function from Flask.
Overall, the code provides a basic implementation of user authentication functionalities in Flask.
Adding and deleting user notes
So far we have created authentication system for user with valid email and password only can create notes. This is how home or index page looks for login in or singup users. Where he can create notes adding nodes in db is explained next.
Adding notes in db is “post” method so we handling it in our home function that is mapped to the root URL path (‘/’). The function is decorated with @views.route”, which is a Flask decorator that maps the function to the specified URL path. Another decorator “@login_required” is used to ensure that only logged-in users can access the homepage; otherwise, they will be redirected to the login page
The function first checks the request method to see if it is a GET or POST request. If it is a POST request, the function gets the “note” from the form and checks if it is at least one character long. If it is not, it flashes an error message. If the note is valid, it creates a new note object and adds it to the database.
The function then returns the rendered “home.html” template and passes the current user as an argument. The template displays the user’s notes and provides a form for adding new notes. If the user is not logged in, they will be redirected to the login page.
Now we will check how to display all notes made by user and how to code for delete operation.
In ‘base.html’ JavaScript function deleteNote
that is called when a user clicks a delete button to remove a note. When the function is called, it sends a POST
request to the server with the noteId
of the note to delete as the request body, using the fetch
function. If the request is successful, it reloads the page to display the updated list of notes.
The flask decorator that handles the POST
request from the deleteNote
function. When a request is received, it loads the request data using the json.loads()
function and extracts the noteId
from the data. It then queries the database for the note with the matching noteId
and checks if the current user is the owner of the note. If the note exists and belongs to the current user, it deletes the note from the database and commits the change. Finally, it returns a JSON response with an empty object to acknowledge the successful deletion.
As further learning you can add this flask application in your website to get better insights!..
You can also check my other’s blog below.