What is Flask and Why Choose It?
Flask is a Python microframework for web development that has gained popularity due to its simplicity and flexibility. Python web development is becoming increasingly in demand, and Flask plays a key role in this as a lightweight but powerful tool.
The main advantage of Flask lies in its minimalism and extensibility. The framework does not impose a rigid architecture and allows developers to use only the necessary components. This makes Flask an ideal choice for creating both small websites and complex web applications.
Benefits of Flask for Web Development
Flask provides developers with numerous advantages:
- Ease of learning and a low entry barrier for beginners.
- Flexibility in choosing architectural solutions and components.
- Active community and a rich ecosystem of extensions.
- Ability to create both prototypes and production-ready applications.
- Full control over the project structure.
Popular Flask extensions include Flask-WTF for working with forms, Flask-Login for authorization, Flask-Migrate for database migrations, and many others.
Installation and First Flask Application
Installing Flask
To get started with Flask, you need to install it via pip:
pip install Flask
Creating a Basic Application
The simplest Flask application might look like this:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "Hello, world!"
if __name__ == '__main__':
app.run(debug=True)
This code creates a web server that responds to GET requests to the root route. The debug=True parameter enables debug mode, which automatically reloads the application when the code is changed.
Flask Project Structure
Proper organization of the project structure is critical for maintaining and developing a web application. A well-structured project facilitates teamwork, testing, and scaling.
Recommended Directory Structure
my_flask_app/
├── app/
│ ├── __init__.py
│ ├── routes.py
│ ├── models.py
│ ├── forms.py
│ └── templates/
│ └── index.html
│ └── static/
├── config.py
└── run.py
Purpose of Files and Folders
__init__.py- application initialization file, contains the creation of the Flask instance.routes.py- defines routes and request handlers.models.py- contains data models for working with the database.forms.py- describes forms using Flask-WTF.templates/- stores HTML templates for displaying pages.static/- contains static files (CSS, JavaScript, images).config.py- application configuration file with settings.run.py- entry point for running the application.
Application Initialization
In the app/__init__.py file, the creation and configuration of the Flask application usually take place:
from flask import Flask
from config import Config
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
from app.routes import bp
app.register_blueprint(bp)
return app
Working with Forms in Flask
Handling user input through forms is one of the main tasks of web development. Flask provides several ways to work with forms, but the most convenient and secure is to use the Flask-WTF extension.
Installing Flask-WTF
pip install flask-wtf
Creating Forms with Flask-WTF
Flask-WTF integrates WTForms with Flask and adds additional security features. Example of creating a login form:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, Length, Email
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=4, max=20)])
password = PasswordField('Password', validators=[DataRequired(), Length(min=6)])
remember_me = BooleanField('Remember me')
submit = SubmitField('Login')
Form Handling in Controllers
The controller handles both GET requests to display the form and POST requests to process data:
from flask import render_template, request, redirect, url_for, flash
from app.forms import LoginForm
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
username = form.username.data
password = form.password.data
# Here should be the user authentication logic
if authenticate_user(username, password):
flash(f'Welcome, {username}!', 'success')
return redirect(url_for('dashboard'))
else:
flash('Incorrect username or password', 'error')
return render_template('login.html', form=form)
Form Data Validation
Flask-WTF provides many built-in validators:
DataRequired()- the field is required to be filled.Length(min, max)- string length check.Email()- email address validation.NumberRange(min, max)- numeric range check.Regexp(regex)- regular expression check.
Working with Sessions in Flask
Sessions allow you to store information about the user between HTTP requests. Flask uses signed cookies to securely store session data on the client-side.
Session Configuration
To work with sessions, you need to set a secret key:
app.secret_key = 'your-secret-key-here'
# Or it is better to use an environment variable
import os
app.secret_key = os.environ.get('SECRET_KEY') or 'fallback-secret-key'
Basic Session Operations
from flask import session
@app.route('/set_session')
def set_session():
session['username'] = 'admin'
session['user_id'] = 123
session.permanent = True # The session will be permanent
return 'Session data set!'
@app.route('/get_session')
def get_session():
username = session.get('username', 'Guest')
user_id = session.get('user_id')
return f'User: {username}, ID: {user_id}'
@app.route('/clear_session')
def clear_session():
session.pop('username', None)
session.pop('user_id', None)
# Or clear the entire session
session.clear()
return 'Session cleared!'
Setting Session Lifetime
from datetime import timedelta
app.permanent_session_lifetime = timedelta(minutes=30)
@app.route('/login')
def login():
session.permanent = True
session['username'] = 'user'
return 'Login performed with a permanent session'
Session Security
Important security aspects when working with sessions:
- Use a cryptographically strong secret key.
- Do not store sensitive data in sessions.
- Regularly update sessions to prevent attacks.
- Clear sessions when the user logs out.
Working with Cookies in Flask
Cookies are small pieces of data that the web server sends to the user's browser. The browser saves them and sends them back to the server in subsequent requests.
Setting Cookies
from flask import make_response, request
@app.route('/set_cookie')
def set_cookie():
resp = make_response('Cookie set!')
resp.set_cookie('username', 'flask_user')
return resp
@app.route('/set_secure_cookie')
def set_secure_cookie():
resp = make_response('Secure cookie set!')
resp.set_cookie('secure_data', 'secret_value',
max_age=3600, # Lifetime in seconds
secure=True, # Only over HTTPS
httponly=True, # Not available to JavaScript
samesite='Strict') # CSRF protection
return resp
Getting Cookies
@app.route('/get_cookie')
def get_cookie():
username = request.cookies.get('username')
if username:
return f'Cookie username: {username}'
else:
return 'Cookie not found'
@app.route('/get_all_cookies')
def get_all_cookies():
cookies = request.cookies
return f'All cookies: {dict(cookies)}'
Deleting Cookies
@app.route('/delete_cookie')
def delete_cookie():
resp = make_response('Cookie deleted!')
resp.delete_cookie('username')
return resp
Cookie Settings
When setting a cookie, you can set various parameters:
max_age- cookie lifetime in seconds.expires- cookie expiration date.domain- domain for which the cookie is valid.path- path on the server for which the cookie is valid.secure- transmit the cookie only over HTTPS.httponly- the cookie is not available to JavaScript.samesite- protection against CSRF attacks.
Full Project Example
Let's consider a comprehensive example demonstrating working with forms, sessions, and cookies in one application:
from flask import Flask, render_template, request, redirect, url_for, session, make_response, flash
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired
from datetime import timedelta
app = Flask(__name__)
app.secret_key = 'supersecretkey'
app.permanent_session_lifetime = timedelta(minutes=30)
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Login')
@app.route('/', methods=['GET', 'POST'])
def home():
form = LoginForm()
if form.validate_on_submit():
username = form.username.data
password = form.password.data
# Simple check (use hashing in a real project)
if username == 'admin' and password == 'secret':
session.permanent = True
session['username'] = username
session['logged_in'] = True
resp = make_response(redirect(url_for('profile')))
resp.set_cookie('last_user', username, max_age=3600)
flash('Login successful!', 'success')
return resp
else:
flash('Incorrect username or password', 'error')
return render_template('login.html', form=form)
@app.route('/profile')
def profile():
if not session.get('logged_in'):
flash('You must be logged in', 'error')
return redirect(url_for('home'))
username = session.get('username', 'Guest')
last_user = request.cookies.get('last_user', 'Unknown')
return render_template('profile.html', username=username, last_user=last_user)
@app.route('/logout')
def logout():
session.clear()
resp = make_response(redirect(url_for('home')))
resp.delete_cookie('last_user')
flash('You have logged out', 'info')
return resp
if __name__ == '__main__':
app.run(debug=True)
Templates for the Example
login.html template
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<form method="POST">
{{ form.hidden_tag() }}
<div>
{{ form.username.label }}
{{ form.username(size=32) }}
{% if form.username.errors %}
<span style="color: red;">{{ form.username.errors[0] }}</span>
{% endif %}
</div>
<div>
{{ form.password.label }}
{{ form.password(size=32) }}
{% if form.password.errors %}
<span style="color: red;">{{ form.password.errors[0] }}</span>
{% endif %}
</div>
<div>
{{ form.submit() }}
</div>
</form>
</body>
</html>
profile.html template
<!DOCTYPE html>
<html>
<head>
<title>User Profile</title>
</head>
<body>
<h1>Welcome, {{ username }}!</h1>
<p>Last login: {{ last_user }}</p>
<a href="{{ url_for('logout') }}">Logout</a>
</body>
</html>
Frequently Asked Questions
What is the difference between Flask and Django?
Flask and Django represent different approaches to web development:
Flask is suitable for:
- Rapid prototyping
- Small and medium-sized projects
- APIs and microservices
- Cases where full control over the architecture is needed
Django is better to choose for:
- Large projects with an administrative panel
- Applications with complex business logic
- Projects where fast development with ready-made solutions is needed
How to ensure form security?
Flask-WTF automatically protects forms from CSRF attacks by adding special tokens. For additional security:
- Use WTForms validators.
- Sanitize user input.
- Use HTTPS to transmit sensitive data.
- Implement proper authentication and authorization.
How to limit the session lifetime?
from datetime import timedelta
app.permanent_session_lifetime = timedelta(minutes=30)
@app.route('/login')
def login():
session.permanent = True
session['username'] = 'user'
return 'Session is active for 30 minutes'
Is it possible to store objects in sessions?
Flask sessions can only store serializable data (strings, numbers, lists, dictionaries). Complex objects need to be serialized to JSON or use other storage methods.
How to work with Jinja2 templates?
Jinja2 is built into Flask. Create HTML files in the templates/ folder and use render_template():
@app.route('/users/<username>')
def user_profile(username):
user_data = {'name': username, 'email': f'{username}@example.com'}
return render_template('user.html', user=user_data)
In the template, you can use variables and conditions:
<h1>Profile {{ user.name }}</h1>
{% if user.email %}
<p>Email: {{ user.email }}</p>
{% endif %}
Best Practices for Flask Development
Code Organization
- Use blueprints to organize routes.
- Move the configuration to separate files.
- Apply the factory pattern to create the application.
- Separate the logic by modules.
Security
- Never store secret keys in code.
- Use environment variables for configuration.
- Enable CSRF protection for all forms.
- Use HTTPS in production.
Performance
- Use caching for frequently requested data.
- Optimize database queries.
- Compress static files.
- Set up proper logging.
Flask provides developers with powerful tools for creating web applications of any complexity. Thanks to the flexibility of the framework, you can start with a simple prototype and gradually develop it into a full-fledged production-ready application. Understanding how to work with forms, sessions, and cookies is essential for creating interactive and secure web applications.
The Future of AI in Mathematics and Everyday Life: How Intelligent Agents Are Already Changing the Game
Experts warned about the risks of fake charity with AI
In Russia, universal AI-agent for robots and industrial processes was developed