Partielo | Créer ta fiche de révision en ligne rapidement

Flask

Introduction

What is flask?

Flask is a web framework that provides libraries to build lightweight web applications in python. It is developed by Armin Ronacher who leads an international group of python enthusiasts (POCCO). It is based on WSGI toolkit and jinja2 template engine. Flask is considered as a micro framework.



What is WSGI?

Web Server Gateway Interface (WSGI) is a standard way for web servers to communicate with Python web applications. It's a specification that describes how requests are forwarded and responses are passed back.



What is Werzeug?

Werkzeug is a comprehensive WSGI utility library in Python used to build web applications. It provides a collection of tools for handling requests, responses, URL routing, and other common web development tasks, making it a foundation for many Python web frameworks like Flask.

Werkzeug is a core library that Flask is built on top of.

Think of Flask as the “web framework” and Werkzeug as the “engine” under the hood that handles HTTP stuff.


🌐 Web Request Flow Diagram

+-------------------+

|  Web Browser    |

| (Client sends a  |

|  request, e.g.   |

|  GET /hello)     |

+--------+----------+

        |

        v

+-------------------+

|  WSGI Server     |

| (Gunicorn/uWSGI) |

| Calls your app    |

+--------+----------+

        |

        v

+-------------------+

|   Flask App      |

| Your routes and |

| logic live here  |

+--------+----------+

        |

        v

+-------------------+

|   Werkzeug       |

| Parses request,  |

| handles routing, |

| builds response  |

+--------+----------+

        |

        v

+-------------------+

|  Flask Returns   |

| Response to WSGI |

| Server            |

+--------+----------+

        |

        v

+-------------------+

| Browser Shows It |

| (HTML/JSON/Text) |

+-------------------+



What is Jinja2?

Jinja2 is a template engine for Python web frameworks like Flask.

It lets you mix Python-like logic (like if, for, variables) into your HTML files, so you can generate dynamic web pages.

Why is Jinja2 used?:

a)      It separates Python code from HTML, making web development cleaner.

b)      It allows you to insert variables, loops, and conditions inside an HTML file.


Advantages of flask:

a) Flask is a lightweight backend framework with minimal dependencies.

b) Flask is easy to learn because its simple and intuitive API makes it easy to learn and use for beginners.

c) Flask is a flexible Framework because it allows you to customize and extend the framework to suit your needs easily.

d) Flask can be used with any database like:- SQL and NoSQL and with any Frontend Technology such as React or Angular.

e) Flask is great for small to medium projects that do not require the complexity of a large framework.

f) Flask Documentation







Virtual Environment setup

·      A virtual environment is an isolated workspace for your Python projects. It allows you to manage and install project-specific dependencies without affecting the system-wide Python installation or other projects.


·      Steps:

a)      Create virtual environment-

python3 -m venv venv

What’s Happening Here:

  • python3 invokes the Python interpreter.
  • -m venv tells Python to run the venv module, which creates a new virtual environment.
  • The second venv is the name of the folder where the environment will be stored. You can name it anything (common names are venv or env).


b)      Activate virtual environment-

venv\Scripts\activate

What Activation Does:

Changes your shell’s PATH variable so that when you run python or pip, it uses the executables from the virtual environment instead of the global ones.

You’ll typically see the environment’s name (like (venv)) appear in your terminal prompt, indicating that the environment is active.


c)      Install project dependencies:

pip install Flask mysql-connector-python

pip is the package manager for Python.

Installing packages here adds them only to the virtual environment, not globally.


d)      Deactivate the virtual environment:

When you’re done working on your project, you can deactivate the virtual environment by running:

deactivate


e)      Solution for powershell restricts :

  • Check current execution policy--

Get-ExecutionPolicy

If it shows "Restricted", that's why you’re getting the error.

  • Temporarily allow script execution

Set-ExecutionPolicy Unrestricted -Scope Process

This will only change the policy for the current terminal session.

It won’t permanently change security settings.

  • Try activating the virtual environment again
  • Alternative: Permanent Fix (Optional)

If you don’t want to repeat this every time, you can permanently change the execution policy:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser


f) The “pip list” command shows all the packages installed in the active environment, in addition to the version numbers of those packages.





First application

from flask import Flask


app = Flask(__name__) # Create the app object


@app.route("/") # Define the route for the home page

def home():

   return "Hello, Flask!" # What will be shown on the web page


if __name__ == "__main__":

   app.run(debug=True) # Run the app in debug mode


1) from flask import Flask-

     Flask is a class inside the flask module, used to create an instance of the web application.


2) app = Flask(__name__) -

Creates an instance of the Flask application.


3) @app.route('/') -

      decorator that maps a URL (/) to a function.


4) def home()

Executes when the root URL (/) is accessed.


5) app.run(debug=True) -

Starts the Flask web server.

debug=True enables Debug Mode, which: Automatically restarts the server when you save changes and shows detailed error messages in the browser.




To remember :

🧠 What is __name__ in Python?

In Python, every script/module has a built-in variable called __name__.

Two Cases:

  • When the script is run directly:

__name__ is set to "__main__"

  • When the script is imported as a module into another script:

__name__ is set to the script’s filename (e.g., 'app', 'utils', etc.)


Example



Why Use if __name__ == "__main__"?

"Only run this part of the code if this file is being run directly — not if it's being imported."








App routing

App Routing means mapping the URLs to a specific function that will handle the logic for that URL.

To bind a function to an URL path we use the app.route decorator.


from flask import Flask


app = Flask(__name__)


@app.route("/")

def home():

   return "Welcome to the Home Page!"


@app.route("/about")

def about():

   return "This is the About Page."


if __name__ == "__main__":

   app.run(debug=True)






Variable rule

Variable Rules allow you to pass dynamic data in the URL by defining placeholders in route paths.

To add variables to URLs, use <variable_name> rule. The function then receives the <variable_name> as keyword argument.

Example:

@app.route("/user/<username>")

def greet_user(username):

   return f"Hello, {username}!"



Additionally, we can also use a converter to convert the variable to a specific data type. By default, it is set to string values. To convert use <converter:variable_name> and following converter types are supported.

string: It is the default type and it accepts any text without a slash.

int: It accepts positive integers.

float: It accepts positive floating-point values.

path: It is like a string but also accepts slashes.

uuid: It accepts UUID strings.

Example:

@app.route("/post/<int:post_id>")

def show_post(post_id):

   return f"You're looking at post {post_id}"



The add_url_rule() function

The URL mapping can also be done using the add_url_rule() function. This approach is mainly used in case we are importing the view function from another module.

Syntax

app.add_url_rule(rule, endpoint=None, view_func=None, **options)

where

rule- URL path (e.g. /about)

endpoint- A unique name for the route, usually the function name.

view_func- The function to call when the route is matched

options- Extra things like methods=['POST'] etc.

Example:

def submit():

   return "Form Submitted!"


app.add_url_rule("/submit", "submit_form", submit, methods=["POST"])







URL building


  • URL building means generating URLs for routes programmatically using the url_for() function, rather than hardcoding them.
  • The first step is to import url_for at the top of your Flask application file.
  • Syntax:

url_for(endpoint_name, **values)

  • The url_for() function is used to build a URL to the specific function dynamically. The first argument is the name of the specified function, and then we can pass any number of keyword argument corresponding to the variable part of the URL.


Example:

@app.route('/user/<username>')

def profile(username):

   return f"User: {username}"


@app.route('/go-to-user')

def go_to_user():

   return url_for('profile', username='john_doe')


If later you change /about to /about-us, you have to manually update every place where you wrote /about.



Adding CSS file-






Redirect

  • redirect() is used to send the user to a different URL.

When do we use it?

  • After form submission
  • After login or logout
  • If someone tries to visit a page they shouldn't see


Example:

from flask import Flask, redirect, url_for


app = Flask(__name__)


@app.route('/')

def home():

   return 'This is the home page'


@app.route('/login')

def login():

   return 'Login page'


@app.route('/dashboard')

def dashboard():

   return redirect(url_for('login'))






abort() function

The abort() function is used to immediately end a request and return an error response to the user — like 404, 403, 401, or 500.

Syntax:

from flask import abort


abort(status_code)


Example:

@app.route('/admin')

def admin():

   user = 'guest'

   if user != 'admin':

       abort(403) # You’re not allowed here!

   return 'Welcome Admin!'







http methods


·      An HTTP method is a way for a client to communicate with a server using the Hypertext Transfer Protocol (HTTP). HTTP methods indicate the action to take on a resource, such as retrieving, updating, or deleting data.

·      Methods:

a)      Post-

o  Suppose, we need to register our details, to a website, OR, upload our files, we will send data, from our browser(the client) to the desired server. The HTTP method, preferred here, is POST. The data sent, from HTML, is then saved, on the server side, post validation. The POST method should be used, when we need to change/add data, on the server side.

o  Example-

html form:

<form action="/submit" method="POST">

   <input type="text" name="username" placeholder="Enter Name">

   <button type="submit">Submit</button>

</form>

flask code:

@app.route('/submit', methods=['POST'])

def submit_form():

   username = request.form['username'] # Extract data from form

   return f"Form submitted! Hello, {username}!"

 

 

b)      Get-

The GET method fetches data from the server.

o  from flask import Flask, request

 

app = Flask(__name__)

 

@app.route('/user')

def get_user():

   name = request.args.get('name') # Extracting 'name' from URL

   return f"Hello, {name}!"

 

if __name__ == '__main__':

   app.run(debug=True)

 

If you visit http://localhost:5000/user?name=John, it will return:

"Hello, John!"


Example-

login.html:
<!DOCTYPE html>
<html>
<head>
   <title>Login</title>
</head>
<body>
   <h2>Login</h2>
   <form action="/login" method="POST">
       <label>Username:</label>
       <input type="text" name="username">
       <br><br>
       <label>Password:</label>
       <input type="password" name="password">
       <br><br>
       <button type="submit">Login</button>
   </form>
</body>
</html>


flask code:

@app.route('/login', methods=['GET', 'POST'])
def login():
   if request.method == 'POST': # Check if form is submitted
       username = request.form['username'] # Get username from form
       password = request.form['password'] # Get password from form
       return f"Logging in {username}..."
   return render_template('login.html') # Show login page

 

👉 What’s different here?

In the previous example (/user), we only needed to read data from the URL, which is done with GET by default. This is why we didn’t write methods=['GET'] explicitly.

However, here we are handling both GET and POST, so we must explicitly mention methods=['GET', 'POST'].












Changing host ip address and port

By default, Flask runs on 127.0.0.1:5000.



from flask import Flask

app = Flask(__name__)


@app.route('/')

def hello():

   return "Hello from Flask!"


if __name__ == '__main__':

   app.run(host='0.0.0.0', port=8080)



------------------------------------------------------------------------------





Database connectivity


A] Using mysql-connector-python (Manual Connection):


db.py:-

import mysql.connector


def get_connection():

  conn = mysql.connector.connect(

    host="localhost",

    user="root",     # your MySQL username

    password="",     # your MySQL password (empty if using XAMPP default)

    database="cravemap_db"

  )

  return conn



app.py:-

from flask import Flask, request, render_template

from db import get_connection


app = Flask(__name__)


@app.route("/")

def home():

  return render_template("register.html")


@app.route("/register", methods=["POST"])

def register():

  username = request.form["username"]

  email = request.form["email"]

  password = request.form["password"]


  conn = get_connection()

  cursor = conn.cursor()

  cursor.execute("INSERT INTO users (username, email, password) VALUES (%s, %s, %s)",

          (username, email, password))

  conn.commit()

  cursor.close()

  conn.close()


  return "Registration successful!"


if __name__ == "__main__":

  app.run(debug=True)



register.html:-

<form action="/register" method="post">

 <input type="text" name="username" placeholder="Username" required><br>

 <input type="email" name="email" placeholder="Email" required><br>

 <input type="password" name="password" placeholder="Password" required><br>

 <button type="submit">Register</button>

</form>


Explanation:

  • mysql.connector.connect(...): This function establishes a connection to the MySQL database.
  • conn = get_connection(): Calls the function get_connection() and opens a connection to MySQL database
  • cursor = conn.cursor() : Creates a cursor object — it acts like a control to interact with the database.
  • cursor.execute() : execute SQL queries.
  • conn.commit() : saves the changes to the database. Without this, the insert will not be permanent.
  • cursor.close() and conn.close() : Closes the cursor and connection.




B] Using Flask-MySQL-Connector (Config-Based):

db.py:-

from flask import Flask, render_template, request

from flask_mysql_connector import MySQL


app = Flask(__name__)


# MySQL Configuration

app.config['MYSQL_HOST'] = 'localhost'

app.config['MYSQL_USER'] = 'root'

app.config['MYSQL_PASSWORD'] = '' # default in XAMPP

app.config['MYSQL_DATABASE'] = 'cravemap_db'


# Initialize MySQL extension

mysql = MySQL(app)


app.py:-

@app.route('/')

def home():

  return render_template("register.html")


@app.route('/register', methods=['POST'])

def register():

  username = request.form['username']

  email = request.form['email']

  password = request.form['password']


  # Use the MySQL connection from the extension

  cursor = mysql.connection.cursor()

  cursor.execute("INSERT INTO users (username, email, password) VALUES (%s, %s, %s)",

          (username, email, password))

  mysql.connection.commit()

  cursor.close()


  return "User registered successfully!"


Explanation:

  • app.config[...] : app.config is a dictionary in Flask used to set configuration settings for your app.
  • MySQL(app) : Initializes the MySQL extension and connects it to your app
  • mysql.connection.cursor() : Lets you execute SQL queries in Flask using the MySQL connection




C] Database connectivity using SQLAlchemy:-

SQLAlchemy is an ORM (Object Relational Mapper) for Python. It allows you to interact with your database using Python classes and objects instead of raw SQL queries.


Step 1 : Install Required Packages

We use pymysql to connect MySQL with Flask. Flask-SQLAlchemy does not talk directly to MySQL — it uses a "connector/driver" behind the scenes.




Step 2 : Create Flask App with SQLAlchemy Setup

app.config['SQLALCHEMY_DATABASE_URI']

So this whole line tells Flask to connect to a MySQL database using root login and no password.


app.config['SQLALCHEMY_TRACK_MODIFICATIONS']

Disables a feature that tracks changes in SQLAlchemy. It’s not needed and uses extra memory, so we set it to False.


db = SQLAlchemy(app)

This initializes SQLAlchemy and connects it to your Flask app.



STEP 4: Define a Table Using a Python Class

User is a Python class that represents your users table in the DB.


db.Model tells SQLAlchemy: "This class maps to a table in the database."

It's a fixed base class from SQLAlchemy that your class must inherit from to become a model.

db.Model is the magic that turns your Python class into a database table.




STEP 5: Create the Table in MySQL


This only creates new tables — it won’t delete or modify existing ones.

Template

What is template?

  • A template is a file that contains both static data (like HTML, CSS) and dynamic placeholders (which will be replaced with real data at runtime).
  • Templates allow the server to send dynamic content to the user instead of just fixed/static HTML pages.

In simple words:

Instead of writing 100 HTML pages manually for different users, you create one template and dynamically fill the page based on data.

Why Templates in Flask?

  • Flask is a micro web framework — it follows the idea of keeping things simple.
  • Flask separates the logic (Python) from the presentation (HTML).
  • You don't mix Python code directly into HTML.
  • Instead, you send data from Python to an HTML template and let the template engine generate the final page.

Benefit: Easier maintenance, cleaner code, and reuse.

How Does Template Work in Flask?

  • Flask uses a template engine called Jinja2 (automatically installed with Flask).
  • Jinja2 can inject dynamic values into static HTML.
  • Jinja2 provides:
  • Variable substitution ({{ variable }})
  • Control flow ({% if %}, {% for %})
  • Filters (modifying output)

Working flow:

  1. A user sends a request (e.g., /profile).
  2. Flask Python code calls render_template().
  3. render_template() finds the HTML file inside the templates/ folder.
  4. Flask fills dynamic values into the HTML and sends the final page to the browser.


render template

1. What is render_template?

  • render_template() is a function provided by Flask.
  • It is used to generate a complete HTML page by combining:
  • A template file (HTML file with placeholders)
  • Dynamic data (variables, lists, objects, etc.)

In short, it renders (fills and prepares) an HTML page by inserting real data into a template.

2. Why is render_template Needed?

  • Flask separates logic (Python) and presentation (HTML).
  • We don’t want to hardcode HTML inside Python.
  • Instead, Python sends data to a template and render_template() prepares the final HTML to be sent to the browser.

4. How Does render_template Work?

Working Flow:

  1. Flask receives a request from the user (like /home).
  2. Flask calls render_template('template.html', data) in the route function.
  3. render_template looks for the specified HTML file inside the templates/ folder.
  4. It processes the HTML file through the Jinja2 template engine.
  5. It inserts all the variables into the placeholders ({{ }}) inside the template.
  6. It sends back the final HTML page to the user’s browser.


5. Syntax of render_template

render_template('template_name.html', variable1=value1, variable2=value2, ...)


Example:

Python file (app.py):

from flask import Flask, render_template


app = Flask(__name__)


@app.route('/')

def home():

   return render_template('index.html', name="Alice")


if __name__ == "__main__":

   app.run(debug=True)



HTML file (templates/index.html):

<!DOCTYPE html>

<html>

<head>

   <title>Home Page</title>

</head>

<body>

   <h1>Hello, {{ name }}!</h1>

</body>

</html>


Writing template

variable

A placeholder in a Flask template is a special tag where dynamic data will be inserted.

Example:

4. What Can You Put Inside Placeholders?

You can use:

  • Variables
  • Expressions
  • Filters
  • Objects' attributes
  • List elements
  • Functions (small ones)


Control structure:


4.1 Conditional Statements (if, elif, else)

{% if user.is_logged_in %}

 <p>Welcome, {{ user.name }}!</p>

{% else %}

 <p>Please log in.</p>

{% endif %}


4.2 Loops (for)

<ul>

 {% for fruit in fruits %}

   <li>{{ fruit }}</li>

 {% endfor %}

</ul>


4.3 else in Loops

<ul>

 {% for fruit in fruits %}

   <li>{{ fruit }}</li>

 {% else %}

   <li>No fruits available.</li>

 {% endfor %}

</ul>


Template inheritance

Use: Reuse the same layout (like header, footer) for multiple pages.

Example

Base template (base.html):

<html>

<body>

 <header>My Website</header>


 {% block content %}{% endblock %}


 <footer>Copyright 2025</footer>

</body>

</html>



Child template (home.html):

{% extends "base.html" %}


{% block content %}

 <h1>Welcome Home!</h1>

{% endblock %}


Static files

Flask expects all static files to be inside a folder called static/ by default.

1. What Are Static Files?

  • Static files are files that don't change when the application runs.
  • They are fixed resources like:
  • CSS files (styling your pages)
  • JavaScript files (adding behavior)
  • Images (logos, backgrounds)
  • Fonts, videos, etc.

✅ They are called "static" because Flask does not modify or generate them dynamically — it just serves them directly to the browser.

Syntax

{{ url_for('static', filename='path/to/file') }}

Examples:

Link a CSS file inside your <head>:

<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">


Link a JavaScript file at the bottom:

<script src="{{ url_for('static', filename='app.js') }}"></script>


Insert an Image:<img src="{{ url_for('static', filename='logo.png') }}" alt="Website Logo">






Uploading


Basic Concepts Involved:




HTML Form (upload.html):


<!-- upload.html -->

<!DOCTYPE html>

<html>

<head>

 <title>Upload File</title>

</head>

<body>

 <h2>Upload a File</h2>

 <form action="/upload" method="POST" enctype="multipart/form-data">

  <input type="file" name="myfile" required><br><br>

  <input type="submit" value="Upload">

 </form>

</body>

</html>


📌 Important:

  • enctype="multipart/form-data" is needed to upload files.
  • myfile is the name we’ll use in Flask to get the file.



Example 1:

from flask import Flask, request, render_template


app = Flask(__name__)


@app.route("/")

def home():

  return render_template("upload.html")


@app.route("/upload", methods=["POST"])

def upload_file():

  file = request.files["myfile"] # Get the file from the form

  if file:

    # Save the file in the same folder as this Python file

    file.save(file.filename)

    return f"File '{file.filename}' uploaded successfully!"

  else:

    return "No file uploaded."


if __name__ == "__main__":

  app.run(debug=True)



Example 2:

from flask import Flask, request, render_template

import mysql.connector

import os


app = Flask(__name__)

UPLOAD_FOLDER = "uploads"


# Make sure uploads folder exists

if not os.path.exists(UPLOAD_FOLDER):

  os.makedirs(UPLOAD_FOLDER)


# MySQL connection

def get_db_connection():

  return mysql.connector.connect(

    host="localhost",

    user="your_mysql_user",

    password="your_mysql_password",

    database="your_db_name"

  )


@app.route("/")

def home():

  return render_template("upload.html")


@app.route("/upload", methods=["POST"])

def upload_file():

  file = request.files["myfile"]

  if file:

    filepath = os.path.join(UPLOAD_FOLDER, file.filename)

    file.save(filepath)


    # Save file info in MySQL

    conn = get_db_connection()

    cursor = conn.cursor()

    sql = "INSERT INTO uploads (filename, filepath) VALUES (%s, %s)"

    cursor.execute(sql, (file.filename, filepath))

    conn.commit()

    conn.close()


    return f"File '{file.filename}' uploaded and saved in database!"

  else:

    return "No file uploaded."


if __name__ == "__main__":

  app.run(debug=True)



Some configuration setting:

a] app.config['UPLOAD_FOLDER']?

  • It’s a Flask configuration variable.
  • It stores the path (folder name) where you want to save uploaded files on your server.


b] app.config['MAX_CONTENT-PATH']

  • It is used to mention the maximum size of the file to be uploaded.




------------------------------------------------------------------------------



flashing


What is Flashing in Flask?

Flashing is a way to display one-time messages to users—such as:

  • "File uploaded successfully."
  • "Login failed. Please try again."
  • "Your profile has been updated."

These messages are usually shown after a redirect, and they disappear once shown.




How Flashing Works:




Example 1:

app.py:

from flask import Flask, flash, redirect, render_template, \

   request, url_for


app = Flask(__name__)

app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'


@app.route('/')

def index():

  return render_template('index.html')


@app.route('/login', methods=['GET', 'POST'])

def login():

  error = None

  if request.method == 'POST':

    if request.form['username'] != 'admin' or \

        request.form['password'] != 'secret':

      error = 'Invalid credentials'

    else:

      flash('You were successfully logged in')

      return redirect(url_for('index'))

  return render_template('login.html', error=error)


html file:

<!doctype html>

<title>My Application</title>

{% with messages = get_flashed_messages() %}

 {% if messages %}

  <ul class=flashes>

  {% for message in messages %}

   <li>{{ message }}</li>

  {% endfor %}

  </ul>

 {% endif %}

{% endwith %}

{% block body %}{% endblock %}




Example 2:

app.py-

from flask import Flask, render_template, request, redirect, url_for, flash


app = Flask(__name__)

app.secret_key = 'your_secret_key' # Required for flashing to work


@app.route('/')

def index():

   return render_template('index.html')


@app.route('/upload', methods=['POST'])

def upload():

   file = request.files.get('file')


   if not file or file.filename == '':

       flash('No file selected!', 'error')

       return redirect(url_for('index'))


   flash('File uploaded successfully!', 'success')

   return redirect(url_for('index'))


index.html-

<!doctype html>

<html>

<head>

 <title>Flashing Example</title>

</head>

<body>

 <form method="POST" action="/upload" enctype="multipart/form-data">

   <input type="file" name="file">

   <input type="submit" value="Upload">

 </form>


 {% with messages = get_flashed_messages(with_categories=true) %}

   {% if messages %}

     <ul>

     {% for category, message in messages %}

       <li style="color: {{ 'red' if category == 'error' else 'green' }}">{{ message }}</li>

     {% endfor %}

     </ul>

   {% endif %}

 {% endwith %}

</body>

</html>


Explanation-

🔸 flash(message, category)

  • Sends a message to the next rendered template.
  • category can be "success", "error", "info", etc. (Optional but useful for styling).

🔸 get_flashed_messages(with_categories=True)

  • Fetches the flashed messages.
  • with_categories=True helps you style different message types.



------------------------------------------------------------------------------



Request object


What is request in flask?

Flask provides a global object called request from the flask module.

It represents the HTTP request sent by the client (browser/user).

Whenever a client sends data to your app (via forms, URL params, JSON, headers, etc.),

you use the request object to read that data.




Common attributes and uses of request:





Example:











Flask

Introduction

What is flask?

Flask is a web framework that provides libraries to build lightweight web applications in python. It is developed by Armin Ronacher who leads an international group of python enthusiasts (POCCO). It is based on WSGI toolkit and jinja2 template engine. Flask is considered as a micro framework.



What is WSGI?

Web Server Gateway Interface (WSGI) is a standard way for web servers to communicate with Python web applications. It's a specification that describes how requests are forwarded and responses are passed back.



What is Werzeug?

Werkzeug is a comprehensive WSGI utility library in Python used to build web applications. It provides a collection of tools for handling requests, responses, URL routing, and other common web development tasks, making it a foundation for many Python web frameworks like Flask.

Werkzeug is a core library that Flask is built on top of.

Think of Flask as the “web framework” and Werkzeug as the “engine” under the hood that handles HTTP stuff.


🌐 Web Request Flow Diagram

+-------------------+

|  Web Browser    |

| (Client sends a  |

|  request, e.g.   |

|  GET /hello)     |

+--------+----------+

        |

        v

+-------------------+

|  WSGI Server     |

| (Gunicorn/uWSGI) |

| Calls your app    |

+--------+----------+

        |

        v

+-------------------+

|   Flask App      |

| Your routes and |

| logic live here  |

+--------+----------+

        |

        v

+-------------------+

|   Werkzeug       |

| Parses request,  |

| handles routing, |

| builds response  |

+--------+----------+

        |

        v

+-------------------+

|  Flask Returns   |

| Response to WSGI |

| Server            |

+--------+----------+

        |

        v

+-------------------+

| Browser Shows It |

| (HTML/JSON/Text) |

+-------------------+



What is Jinja2?

Jinja2 is a template engine for Python web frameworks like Flask.

It lets you mix Python-like logic (like if, for, variables) into your HTML files, so you can generate dynamic web pages.

Why is Jinja2 used?:

a)      It separates Python code from HTML, making web development cleaner.

b)      It allows you to insert variables, loops, and conditions inside an HTML file.


Advantages of flask:

a) Flask is a lightweight backend framework with minimal dependencies.

b) Flask is easy to learn because its simple and intuitive API makes it easy to learn and use for beginners.

c) Flask is a flexible Framework because it allows you to customize and extend the framework to suit your needs easily.

d) Flask can be used with any database like:- SQL and NoSQL and with any Frontend Technology such as React or Angular.

e) Flask is great for small to medium projects that do not require the complexity of a large framework.

f) Flask Documentation







Virtual Environment setup

·      A virtual environment is an isolated workspace for your Python projects. It allows you to manage and install project-specific dependencies without affecting the system-wide Python installation or other projects.


·      Steps:

a)      Create virtual environment-

python3 -m venv venv

What’s Happening Here:

  • python3 invokes the Python interpreter.
  • -m venv tells Python to run the venv module, which creates a new virtual environment.
  • The second venv is the name of the folder where the environment will be stored. You can name it anything (common names are venv or env).


b)      Activate virtual environment-

venv\Scripts\activate

What Activation Does:

Changes your shell’s PATH variable so that when you run python or pip, it uses the executables from the virtual environment instead of the global ones.

You’ll typically see the environment’s name (like (venv)) appear in your terminal prompt, indicating that the environment is active.


c)      Install project dependencies:

pip install Flask mysql-connector-python

pip is the package manager for Python.

Installing packages here adds them only to the virtual environment, not globally.


d)      Deactivate the virtual environment:

When you’re done working on your project, you can deactivate the virtual environment by running:

deactivate


e)      Solution for powershell restricts :

  • Check current execution policy--

Get-ExecutionPolicy

If it shows "Restricted", that's why you’re getting the error.

  • Temporarily allow script execution

Set-ExecutionPolicy Unrestricted -Scope Process

This will only change the policy for the current terminal session.

It won’t permanently change security settings.

  • Try activating the virtual environment again
  • Alternative: Permanent Fix (Optional)

If you don’t want to repeat this every time, you can permanently change the execution policy:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser


f) The “pip list” command shows all the packages installed in the active environment, in addition to the version numbers of those packages.





First application

from flask import Flask


app = Flask(__name__) # Create the app object


@app.route("/") # Define the route for the home page

def home():

   return "Hello, Flask!" # What will be shown on the web page


if __name__ == "__main__":

   app.run(debug=True) # Run the app in debug mode


1) from flask import Flask-

     Flask is a class inside the flask module, used to create an instance of the web application.


2) app = Flask(__name__) -

Creates an instance of the Flask application.


3) @app.route('/') -

      decorator that maps a URL (/) to a function.


4) def home()

Executes when the root URL (/) is accessed.


5) app.run(debug=True) -

Starts the Flask web server.

debug=True enables Debug Mode, which: Automatically restarts the server when you save changes and shows detailed error messages in the browser.




To remember :

🧠 What is __name__ in Python?

In Python, every script/module has a built-in variable called __name__.

Two Cases:

  • When the script is run directly:

__name__ is set to "__main__"

  • When the script is imported as a module into another script:

__name__ is set to the script’s filename (e.g., 'app', 'utils', etc.)


Example



Why Use if __name__ == "__main__"?

"Only run this part of the code if this file is being run directly — not if it's being imported."








App routing

App Routing means mapping the URLs to a specific function that will handle the logic for that URL.

To bind a function to an URL path we use the app.route decorator.


from flask import Flask


app = Flask(__name__)


@app.route("/")

def home():

   return "Welcome to the Home Page!"


@app.route("/about")

def about():

   return "This is the About Page."


if __name__ == "__main__":

   app.run(debug=True)






Variable rule

Variable Rules allow you to pass dynamic data in the URL by defining placeholders in route paths.

To add variables to URLs, use <variable_name> rule. The function then receives the <variable_name> as keyword argument.

Example:

@app.route("/user/<username>")

def greet_user(username):

   return f"Hello, {username}!"



Additionally, we can also use a converter to convert the variable to a specific data type. By default, it is set to string values. To convert use <converter:variable_name> and following converter types are supported.

string: It is the default type and it accepts any text without a slash.

int: It accepts positive integers.

float: It accepts positive floating-point values.

path: It is like a string but also accepts slashes.

uuid: It accepts UUID strings.

Example:

@app.route("/post/<int:post_id>")

def show_post(post_id):

   return f"You're looking at post {post_id}"



The add_url_rule() function

The URL mapping can also be done using the add_url_rule() function. This approach is mainly used in case we are importing the view function from another module.

Syntax

app.add_url_rule(rule, endpoint=None, view_func=None, **options)

where

rule- URL path (e.g. /about)

endpoint- A unique name for the route, usually the function name.

view_func- The function to call when the route is matched

options- Extra things like methods=['POST'] etc.

Example:

def submit():

   return "Form Submitted!"


app.add_url_rule("/submit", "submit_form", submit, methods=["POST"])







URL building


  • URL building means generating URLs for routes programmatically using the url_for() function, rather than hardcoding them.
  • The first step is to import url_for at the top of your Flask application file.
  • Syntax:

url_for(endpoint_name, **values)

  • The url_for() function is used to build a URL to the specific function dynamically. The first argument is the name of the specified function, and then we can pass any number of keyword argument corresponding to the variable part of the URL.


Example:

@app.route('/user/<username>')

def profile(username):

   return f"User: {username}"


@app.route('/go-to-user')

def go_to_user():

   return url_for('profile', username='john_doe')


If later you change /about to /about-us, you have to manually update every place where you wrote /about.



Adding CSS file-






Redirect

  • redirect() is used to send the user to a different URL.

When do we use it?

  • After form submission
  • After login or logout
  • If someone tries to visit a page they shouldn't see


Example:

from flask import Flask, redirect, url_for


app = Flask(__name__)


@app.route('/')

def home():

   return 'This is the home page'


@app.route('/login')

def login():

   return 'Login page'


@app.route('/dashboard')

def dashboard():

   return redirect(url_for('login'))






abort() function

The abort() function is used to immediately end a request and return an error response to the user — like 404, 403, 401, or 500.

Syntax:

from flask import abort


abort(status_code)


Example:

@app.route('/admin')

def admin():

   user = 'guest'

   if user != 'admin':

       abort(403) # You’re not allowed here!

   return 'Welcome Admin!'







http methods


·      An HTTP method is a way for a client to communicate with a server using the Hypertext Transfer Protocol (HTTP). HTTP methods indicate the action to take on a resource, such as retrieving, updating, or deleting data.

·      Methods:

a)      Post-

o  Suppose, we need to register our details, to a website, OR, upload our files, we will send data, from our browser(the client) to the desired server. The HTTP method, preferred here, is POST. The data sent, from HTML, is then saved, on the server side, post validation. The POST method should be used, when we need to change/add data, on the server side.

o  Example-

html form:

<form action="/submit" method="POST">

   <input type="text" name="username" placeholder="Enter Name">

   <button type="submit">Submit</button>

</form>

flask code:

@app.route('/submit', methods=['POST'])

def submit_form():

   username = request.form['username'] # Extract data from form

   return f"Form submitted! Hello, {username}!"

 

 

b)      Get-

The GET method fetches data from the server.

o  from flask import Flask, request

 

app = Flask(__name__)

 

@app.route('/user')

def get_user():

   name = request.args.get('name') # Extracting 'name' from URL

   return f"Hello, {name}!"

 

if __name__ == '__main__':

   app.run(debug=True)

 

If you visit http://localhost:5000/user?name=John, it will return:

"Hello, John!"


Example-

login.html:
<!DOCTYPE html>
<html>
<head>
   <title>Login</title>
</head>
<body>
   <h2>Login</h2>
   <form action="/login" method="POST">
       <label>Username:</label>
       <input type="text" name="username">
       <br><br>
       <label>Password:</label>
       <input type="password" name="password">
       <br><br>
       <button type="submit">Login</button>
   </form>
</body>
</html>


flask code:

@app.route('/login', methods=['GET', 'POST'])
def login():
   if request.method == 'POST': # Check if form is submitted
       username = request.form['username'] # Get username from form
       password = request.form['password'] # Get password from form
       return f"Logging in {username}..."
   return render_template('login.html') # Show login page

 

👉 What’s different here?

In the previous example (/user), we only needed to read data from the URL, which is done with GET by default. This is why we didn’t write methods=['GET'] explicitly.

However, here we are handling both GET and POST, so we must explicitly mention methods=['GET', 'POST'].












Changing host ip address and port

By default, Flask runs on 127.0.0.1:5000.



from flask import Flask

app = Flask(__name__)


@app.route('/')

def hello():

   return "Hello from Flask!"


if __name__ == '__main__':

   app.run(host='0.0.0.0', port=8080)



------------------------------------------------------------------------------





Database connectivity


A] Using mysql-connector-python (Manual Connection):


db.py:-

import mysql.connector


def get_connection():

  conn = mysql.connector.connect(

    host="localhost",

    user="root",     # your MySQL username

    password="",     # your MySQL password (empty if using XAMPP default)

    database="cravemap_db"

  )

  return conn



app.py:-

from flask import Flask, request, render_template

from db import get_connection


app = Flask(__name__)


@app.route("/")

def home():

  return render_template("register.html")


@app.route("/register", methods=["POST"])

def register():

  username = request.form["username"]

  email = request.form["email"]

  password = request.form["password"]


  conn = get_connection()

  cursor = conn.cursor()

  cursor.execute("INSERT INTO users (username, email, password) VALUES (%s, %s, %s)",

          (username, email, password))

  conn.commit()

  cursor.close()

  conn.close()


  return "Registration successful!"


if __name__ == "__main__":

  app.run(debug=True)



register.html:-

<form action="/register" method="post">

 <input type="text" name="username" placeholder="Username" required><br>

 <input type="email" name="email" placeholder="Email" required><br>

 <input type="password" name="password" placeholder="Password" required><br>

 <button type="submit">Register</button>

</form>


Explanation:

  • mysql.connector.connect(...): This function establishes a connection to the MySQL database.
  • conn = get_connection(): Calls the function get_connection() and opens a connection to MySQL database
  • cursor = conn.cursor() : Creates a cursor object — it acts like a control to interact with the database.
  • cursor.execute() : execute SQL queries.
  • conn.commit() : saves the changes to the database. Without this, the insert will not be permanent.
  • cursor.close() and conn.close() : Closes the cursor and connection.




B] Using Flask-MySQL-Connector (Config-Based):

db.py:-

from flask import Flask, render_template, request

from flask_mysql_connector import MySQL


app = Flask(__name__)


# MySQL Configuration

app.config['MYSQL_HOST'] = 'localhost'

app.config['MYSQL_USER'] = 'root'

app.config['MYSQL_PASSWORD'] = '' # default in XAMPP

app.config['MYSQL_DATABASE'] = 'cravemap_db'


# Initialize MySQL extension

mysql = MySQL(app)


app.py:-

@app.route('/')

def home():

  return render_template("register.html")


@app.route('/register', methods=['POST'])

def register():

  username = request.form['username']

  email = request.form['email']

  password = request.form['password']


  # Use the MySQL connection from the extension

  cursor = mysql.connection.cursor()

  cursor.execute("INSERT INTO users (username, email, password) VALUES (%s, %s, %s)",

          (username, email, password))

  mysql.connection.commit()

  cursor.close()


  return "User registered successfully!"


Explanation:

  • app.config[...] : app.config is a dictionary in Flask used to set configuration settings for your app.
  • MySQL(app) : Initializes the MySQL extension and connects it to your app
  • mysql.connection.cursor() : Lets you execute SQL queries in Flask using the MySQL connection




C] Database connectivity using SQLAlchemy:-

SQLAlchemy is an ORM (Object Relational Mapper) for Python. It allows you to interact with your database using Python classes and objects instead of raw SQL queries.


Step 1 : Install Required Packages

We use pymysql to connect MySQL with Flask. Flask-SQLAlchemy does not talk directly to MySQL — it uses a "connector/driver" behind the scenes.




Step 2 : Create Flask App with SQLAlchemy Setup

app.config['SQLALCHEMY_DATABASE_URI']

So this whole line tells Flask to connect to a MySQL database using root login and no password.


app.config['SQLALCHEMY_TRACK_MODIFICATIONS']

Disables a feature that tracks changes in SQLAlchemy. It’s not needed and uses extra memory, so we set it to False.


db = SQLAlchemy(app)

This initializes SQLAlchemy and connects it to your Flask app.



STEP 4: Define a Table Using a Python Class

User is a Python class that represents your users table in the DB.


db.Model tells SQLAlchemy: "This class maps to a table in the database."

It's a fixed base class from SQLAlchemy that your class must inherit from to become a model.

db.Model is the magic that turns your Python class into a database table.




STEP 5: Create the Table in MySQL


This only creates new tables — it won’t delete or modify existing ones.

Template

What is template?

  • A template is a file that contains both static data (like HTML, CSS) and dynamic placeholders (which will be replaced with real data at runtime).
  • Templates allow the server to send dynamic content to the user instead of just fixed/static HTML pages.

In simple words:

Instead of writing 100 HTML pages manually for different users, you create one template and dynamically fill the page based on data.

Why Templates in Flask?

  • Flask is a micro web framework — it follows the idea of keeping things simple.
  • Flask separates the logic (Python) from the presentation (HTML).
  • You don't mix Python code directly into HTML.
  • Instead, you send data from Python to an HTML template and let the template engine generate the final page.

Benefit: Easier maintenance, cleaner code, and reuse.

How Does Template Work in Flask?

  • Flask uses a template engine called Jinja2 (automatically installed with Flask).
  • Jinja2 can inject dynamic values into static HTML.
  • Jinja2 provides:
  • Variable substitution ({{ variable }})
  • Control flow ({% if %}, {% for %})
  • Filters (modifying output)

Working flow:

  1. A user sends a request (e.g., /profile).
  2. Flask Python code calls render_template().
  3. render_template() finds the HTML file inside the templates/ folder.
  4. Flask fills dynamic values into the HTML and sends the final page to the browser.


render template

1. What is render_template?

  • render_template() is a function provided by Flask.
  • It is used to generate a complete HTML page by combining:
  • A template file (HTML file with placeholders)
  • Dynamic data (variables, lists, objects, etc.)

In short, it renders (fills and prepares) an HTML page by inserting real data into a template.

2. Why is render_template Needed?

  • Flask separates logic (Python) and presentation (HTML).
  • We don’t want to hardcode HTML inside Python.
  • Instead, Python sends data to a template and render_template() prepares the final HTML to be sent to the browser.

4. How Does render_template Work?

Working Flow:

  1. Flask receives a request from the user (like /home).
  2. Flask calls render_template('template.html', data) in the route function.
  3. render_template looks for the specified HTML file inside the templates/ folder.
  4. It processes the HTML file through the Jinja2 template engine.
  5. It inserts all the variables into the placeholders ({{ }}) inside the template.
  6. It sends back the final HTML page to the user’s browser.


5. Syntax of render_template

render_template('template_name.html', variable1=value1, variable2=value2, ...)


Example:

Python file (app.py):

from flask import Flask, render_template


app = Flask(__name__)


@app.route('/')

def home():

   return render_template('index.html', name="Alice")


if __name__ == "__main__":

   app.run(debug=True)



HTML file (templates/index.html):

<!DOCTYPE html>

<html>

<head>

   <title>Home Page</title>

</head>

<body>

   <h1>Hello, {{ name }}!</h1>

</body>

</html>


Writing template

variable

A placeholder in a Flask template is a special tag where dynamic data will be inserted.

Example:

4. What Can You Put Inside Placeholders?

You can use:

  • Variables
  • Expressions
  • Filters
  • Objects' attributes
  • List elements
  • Functions (small ones)


Control structure:


4.1 Conditional Statements (if, elif, else)

{% if user.is_logged_in %}

 <p>Welcome, {{ user.name }}!</p>

{% else %}

 <p>Please log in.</p>

{% endif %}


4.2 Loops (for)

<ul>

 {% for fruit in fruits %}

   <li>{{ fruit }}</li>

 {% endfor %}

</ul>


4.3 else in Loops

<ul>

 {% for fruit in fruits %}

   <li>{{ fruit }}</li>

 {% else %}

   <li>No fruits available.</li>

 {% endfor %}

</ul>


Template inheritance

Use: Reuse the same layout (like header, footer) for multiple pages.

Example

Base template (base.html):

<html>

<body>

 <header>My Website</header>


 {% block content %}{% endblock %}


 <footer>Copyright 2025</footer>

</body>

</html>



Child template (home.html):

{% extends "base.html" %}


{% block content %}

 <h1>Welcome Home!</h1>

{% endblock %}


Static files

Flask expects all static files to be inside a folder called static/ by default.

1. What Are Static Files?

  • Static files are files that don't change when the application runs.
  • They are fixed resources like:
  • CSS files (styling your pages)
  • JavaScript files (adding behavior)
  • Images (logos, backgrounds)
  • Fonts, videos, etc.

✅ They are called "static" because Flask does not modify or generate them dynamically — it just serves them directly to the browser.

Syntax

{{ url_for('static', filename='path/to/file') }}

Examples:

Link a CSS file inside your <head>:

<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">


Link a JavaScript file at the bottom:

<script src="{{ url_for('static', filename='app.js') }}"></script>


Insert an Image:<img src="{{ url_for('static', filename='logo.png') }}" alt="Website Logo">






Uploading


Basic Concepts Involved:




HTML Form (upload.html):


<!-- upload.html -->

<!DOCTYPE html>

<html>

<head>

 <title>Upload File</title>

</head>

<body>

 <h2>Upload a File</h2>

 <form action="/upload" method="POST" enctype="multipart/form-data">

  <input type="file" name="myfile" required><br><br>

  <input type="submit" value="Upload">

 </form>

</body>

</html>


📌 Important:

  • enctype="multipart/form-data" is needed to upload files.
  • myfile is the name we’ll use in Flask to get the file.



Example 1:

from flask import Flask, request, render_template


app = Flask(__name__)


@app.route("/")

def home():

  return render_template("upload.html")


@app.route("/upload", methods=["POST"])

def upload_file():

  file = request.files["myfile"] # Get the file from the form

  if file:

    # Save the file in the same folder as this Python file

    file.save(file.filename)

    return f"File '{file.filename}' uploaded successfully!"

  else:

    return "No file uploaded."


if __name__ == "__main__":

  app.run(debug=True)



Example 2:

from flask import Flask, request, render_template

import mysql.connector

import os


app = Flask(__name__)

UPLOAD_FOLDER = "uploads"


# Make sure uploads folder exists

if not os.path.exists(UPLOAD_FOLDER):

  os.makedirs(UPLOAD_FOLDER)


# MySQL connection

def get_db_connection():

  return mysql.connector.connect(

    host="localhost",

    user="your_mysql_user",

    password="your_mysql_password",

    database="your_db_name"

  )


@app.route("/")

def home():

  return render_template("upload.html")


@app.route("/upload", methods=["POST"])

def upload_file():

  file = request.files["myfile"]

  if file:

    filepath = os.path.join(UPLOAD_FOLDER, file.filename)

    file.save(filepath)


    # Save file info in MySQL

    conn = get_db_connection()

    cursor = conn.cursor()

    sql = "INSERT INTO uploads (filename, filepath) VALUES (%s, %s)"

    cursor.execute(sql, (file.filename, filepath))

    conn.commit()

    conn.close()


    return f"File '{file.filename}' uploaded and saved in database!"

  else:

    return "No file uploaded."


if __name__ == "__main__":

  app.run(debug=True)



Some configuration setting:

a] app.config['UPLOAD_FOLDER']?

  • It’s a Flask configuration variable.
  • It stores the path (folder name) where you want to save uploaded files on your server.


b] app.config['MAX_CONTENT-PATH']

  • It is used to mention the maximum size of the file to be uploaded.




------------------------------------------------------------------------------



flashing


What is Flashing in Flask?

Flashing is a way to display one-time messages to users—such as:

  • "File uploaded successfully."
  • "Login failed. Please try again."
  • "Your profile has been updated."

These messages are usually shown after a redirect, and they disappear once shown.




How Flashing Works:




Example 1:

app.py:

from flask import Flask, flash, redirect, render_template, \

   request, url_for


app = Flask(__name__)

app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'


@app.route('/')

def index():

  return render_template('index.html')


@app.route('/login', methods=['GET', 'POST'])

def login():

  error = None

  if request.method == 'POST':

    if request.form['username'] != 'admin' or \

        request.form['password'] != 'secret':

      error = 'Invalid credentials'

    else:

      flash('You were successfully logged in')

      return redirect(url_for('index'))

  return render_template('login.html', error=error)


html file:

<!doctype html>

<title>My Application</title>

{% with messages = get_flashed_messages() %}

 {% if messages %}

  <ul class=flashes>

  {% for message in messages %}

   <li>{{ message }}</li>

  {% endfor %}

  </ul>

 {% endif %}

{% endwith %}

{% block body %}{% endblock %}




Example 2:

app.py-

from flask import Flask, render_template, request, redirect, url_for, flash


app = Flask(__name__)

app.secret_key = 'your_secret_key' # Required for flashing to work


@app.route('/')

def index():

   return render_template('index.html')


@app.route('/upload', methods=['POST'])

def upload():

   file = request.files.get('file')


   if not file or file.filename == '':

       flash('No file selected!', 'error')

       return redirect(url_for('index'))


   flash('File uploaded successfully!', 'success')

   return redirect(url_for('index'))


index.html-

<!doctype html>

<html>

<head>

 <title>Flashing Example</title>

</head>

<body>

 <form method="POST" action="/upload" enctype="multipart/form-data">

   <input type="file" name="file">

   <input type="submit" value="Upload">

 </form>


 {% with messages = get_flashed_messages(with_categories=true) %}

   {% if messages %}

     <ul>

     {% for category, message in messages %}

       <li style="color: {{ 'red' if category == 'error' else 'green' }}">{{ message }}</li>

     {% endfor %}

     </ul>

   {% endif %}

 {% endwith %}

</body>

</html>


Explanation-

🔸 flash(message, category)

  • Sends a message to the next rendered template.
  • category can be "success", "error", "info", etc. (Optional but useful for styling).

🔸 get_flashed_messages(with_categories=True)

  • Fetches the flashed messages.
  • with_categories=True helps you style different message types.



------------------------------------------------------------------------------



Request object


What is request in flask?

Flask provides a global object called request from the flask module.

It represents the HTTP request sent by the client (browser/user).

Whenever a client sends data to your app (via forms, URL params, JSON, headers, etc.),

you use the request object to read that data.




Common attributes and uses of request:





Example:










Retour

Actions