form handling in Flask student notes part-III (2)
form handling in Flask student notes part-III (2)
● Forms are an essential part of web development, allowing users to input data that your
application can process. Flask provides a simple and flexible way to handle forms using
the request object.
● To send the data using the HTML form page, generally we use GET or POST methods
of the HTTP protocol.
What is GET?
What is POST?
● Use GET:
○ When the action is idempotent (does not change data on the server).
○ For search forms, filters, or non-sensitive data submissions.
● Use POST:
○ For actions that modify server-side data.
○ For sensitive data submissions like passwords or large payloads.
● Design a form in HTML using <form> tags. Define the action (url_for
endpoint) and the HTTP method (GET or POST).
Folder Structure:
FlaskFormApp
|
|-- app.py
|
|--templates
|
|--user_form.html
|--result.html
user_form.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body bgcolor="cyan">
<form action="{{url_for('add')}}">
<br><br>
</form>
</body>
</html>
app.py:
@app.route('/')
def home():
return render_template('user_form.html')
@app.route("/add", methods=["GET"])
def add():
n1 = request.args.get("n1")
n2 = request.args.get("n2")
result = float(n1) + float(n2)
return render_template("result.html", result=result)
if __name__ == '__main__':
app.run(debug=True)
result.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body bgcolor="yellow">
</body>
</html>
Note: Since form data is sent here without mentioning the method, it is using the GET method
by default. and the data is visible to the URL also.
In order to send the data using the POST method from the html form page and handle the form
POST data inside the view function do the following modification in the above example:
@app.route("/add", methods=["POST"])
def add():
# n1 = request.form["n1"]
n1 = request.form.get("n1")
n2 = request.form.get("n2")
result = float(n1) + float(n2)
return render_template("result.html", result=result)
Example: Modification of the above program to display the result to the same page.Using
POST method.
user_form.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body bgcolor="cyan">
<br><br>
<br><br>
<hr>
<!-- {% if result %} -->
{% if result%}
<h2>The Result is {{result}}</h2>
{% endif %}
</body>
</html>
app.py:
if request.method == "POST":
# n1 = request.form["n1"]
n1 = request.form.get("n1")
n2 = request.form.get("n2")
sum= float(n1) + float(n2)
if __name__ == '__main__':
app.run(debug=True)
Solution:
FlaskLoginApp
|
|-- app.py
|
|--templates
|
|--user_form.html
|--profile.html
app.py
app = Flask(__name__)
app.secret_key = "My Secret key"
@app.route('/') # 127.0.0.1:5000/
def home():
return render_template("user_form.html")
@app.route("/profile")
def profile():
name = session.get("name")
if name:
return render_template("profile.html", name=name)
else:
return redirect(url_for("home"))
@app.route("/logout")
def logout():
session.pop("name", None) # Remove 'name' from session
return redirect(url_for("home"))
if __name__ == "__main__":
app.run(debug=True)
user_form.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body bgcolor="cyan">
<br><br>
<br><br>
<label for="password">Enter Password:</label>
<input type="password" id="password" name="password" required>
<br><br>
</form>
{% if result %}
<h2 style="color:red">{{result}}</h2>
{% endif %}
</body>
</html>
profile.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body bgcolor="yellow">
<a href="{{url_for('logout')}}">Logout</a>
</body>
</html>
What is app.secret_key?
Scenario:
Imagine you are hosting a private party 🎉, and you want to allow only people with an invitation
card to enter. The invitation card has a special seal that only you can create, so nobody can fake an
invitation.
In Flask, the SECRET_KEY acts like that special seal. It helps Flask verify that data (like cookies or
session data) has not been modified or faked by someone else.
🔹 The session data is signed using SECRET_KEY so that no one can tamper with it.
🔹 If a hacker tries to modify the session data without the correct SECRET_KEY, Flask will reject it.
Using the Flash messages: (Message flashing)
● Flash messages in Flask are a mechanism for sending one-time messages from the
server to the client, typically to notify users about the result of an action (e.g., success,
error, or warning). They are a great way to provide feedback to users after performing
operations like logging in, signing up, or submitting forms.
● Message Flashing means when we click on any button( any website ) and the website
sends immediately any message that can be an error, alert, or any type of message, it is
called the Message Flashing and when that happens in a flask or we are creating any
website which shows an alert, error type message than its called as Flask-Message
Flashing.
1. Temporary Storage: Flash messages are stored in the session, which means they
persist only for a single request.
2. flash() Function: Used to add a message to the session's flash storage.
3. get_flashed_messages() Function: Used to retrieve and display the flash
messages in templates(inside the HTML).
Syntax:
flash(message, category)
Example:
Example:
Without category:
<h3 style="color:red">{{messages}}</h3>
{% endfor %}
With category:
{% for category, messages in get_flashed_messages(with_categories=True) %}
{% endfor %}
With Bootstrap:
● Make sure that bootstrap related JavaScript also included.
{% for category,messages in get_flashed_messages(with_categories=True) %}
{% endfor %}
Key Features
1. Categorization: Flash messages can have categories (success, info, error, etc.),
which are useful for styling.
2. Bootstrap Integration: Works seamlessly with Bootstrap's alert classes for better
styling.
3. One-Time Messages: Flash messages are automatically removed after being displayed
once.
4. Custom Filters: Use category_filter in get_flashed_messages() to retrieve
specific message categories.
app.py:
app = Flask(__name__)
app.secret_key = "My Secret key"
@app.route('/') # 127.0.0.1:5000/
def home():
return render_template("user_form.html")
@app.route("/profile")
def profile():
name = session.get("name")
if name:
return render_template("profile.html", name=name)
else:
flash("Please login first", "warning")
return redirect(url_for("home"))
@app.route("/logout")
def logout():
session.pop("name", None) # Remove 'name' from session
flash("You have been logged out.", "info")
return redirect(url_for("home"))
if __name__ == "__main__":
app.run(debug=True)
user_form.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.
css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6h
W+ALEwIH" crossorigin="anonymous">
</head>
<body bgcolor="cyan">
<h1 style="text-align: center;">Welcome to Chitkara</h1>
<br><br>
<br><br>
<label for="password">Enter Password:</label>
<input type="password" id="password" name="password" required>
<br><br>
</form>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle
.min.js"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN
7N6jIeHz"
crossorigin="anonymous"></script>
</body>
</html>
profile.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body bgcolor="yellow">
<a href="{{url_for('logout')}}">Logout</a>
</body>
</html>
Example: Creating a Form to capture the Student information(roll, name, address, marks) and
showing the student information below the form page inside a table.
Folder Structure:
FlaskStudentApp2
|
|-- app.py
|
|--templates
|
|--base.html
|--index.html
|--student.htmll
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title_block %} {% endblock %}</title>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.
css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6h
W+ALEwIH" crossorigin="anonymous">
<style>
body {
margin: 0;
padding: 0;
}
header {
background-color: aqua;
height: 10vh;
}
main {
background-color: antiquewhite;
height: 80vh;
}
footer {
background-color: aquamarine;
height: 10vh;
}
</style>
</head>
<body bgcolor="Cyan">
<header>
<h1 class="text-center">Welcome to Chitkara</h1>
</header>
<main>
{% block main_block %}
{% endblock %}
</main>
<footer>
<p class="text-center">© 2025 Student Information System</p>
</footer>
</body>
</html>
index.html:
{% extends "base.html" %}
{% block main_block %}
{% endblock %}
app.py:
students = []
@app.route("/")
def index():
return render_template("index.html")
@app.route("/student", methods=["GET", "POST"])
def student():
if request.method == "POST":
# Fetch the form data
roll = request.form.get("roll")
name = request.form.get("name")
address = request.form.get("address")
marks = request.form.get("marks")
if __name__ == '__main__':
app.run(debug=True)
student.html:
{% extends "base.html" %}
{% block main_block %}
<a href="{{url_for('index')}}">Back</a>
</div>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name"
placeholder="Enter Name" name="name" required>
</div>
<div class="form-group">
<label for="address">Address</label>
<input type="text" class="form-control" id="address"
placeholder="Enter Address" name="address" required>
</div>
<div class="form-group">
<label for="marks">Marks</label>
<input type="number" class="form-control" id="marks"
placeholder="Enter Marks" name="marks" required>
</div>
{% if students %}
<hr>
<thead>
<tr>
<th>Roll Number</th>
<th>Student Name</th>
<th>Student Address</th>
<th>Student Marks</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{student.roll}}</td>
<td>{{student.name}}</td>
<td>{{student.address}}</td>
<td>{{student.marks}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock %}
Note: The students list is currently stored globally, which works fine for now but may lead to
issues with concurrency in larger-scale applications. In a production environment, it's
recommended to store it permanently in a database or inside a file for better scalability and
data persistence.
Storing inside a file:
● If you want data to persist even after the server restarts, you can store the student
information in a file (e.g., a JSON or CSV file). This is still a simple solution, but it can be
more reliable than using a global variable for storing persistent data.
● Modify the app.py file as follows:
app.py:
app = Flask(__name__)
def load_students():
try:
with open("students.json", "r") as f:
students = json.load(f)
return students
except Exception as e:
print(f"An Error occurred {e}")
return []
def save_students(students):
with open("students.json", "w") as f:
json.dump(students, f)
@app.route("/")
def index():
return render_template("index.html")
if request.method == "POST":
# Fetch the form data
roll = request.form.get("roll")
name = request.form.get("name")
address = request.form.get("address")
marks = request.form.get("marks")
if __name__ == '__main__':
app.run(debug=True)