Flask: микрофреймворк для веб-разработки на Python
Основы работы с Flask
Наиболее эффективное решение для старта веб-приложения на Flask - минимальный проект с одним маршрутом и шаблоном. Это позволяет быстро увидеть результат и понять архитектуру.
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html', title='Главная')
if __name__ == '__main__':
app.run(debug=True)фреймворк flask python (фреймворк flask в python)
После запуска по адресу http://127.0.0.1:5000 откроется страница, сгенерированная шаблоном index.html. Режим debug=True позволяет автоматически перезагружать сервер при изменениях кода и показывает подробные сообщения об ошибках.
Типичная ошибка: если папка templates не создана или имя шаблона указано неверно, возникает TemplateNotFound. Решение - создать папку templates в корне проекта и поместить туда файл index.html.
Как передать параметр в маршрут?
@app.route('/user/<username>')
def user_profile(username):
return f'Привет, {username}!'
Такой маршрут обрабатывает URL вида /user/ivan. Параметр username автоматически передаётся в функцию. Можно указать тип: <int:user_id> для целых чисел.
Проблема: если переменная не соответствует типу (например, строка для int), Flask вернёт 404. Следует проверять данные или использовать кастомный конвертер.
Как использовать шаблоны с циклами и условиями?
В файле шаблона (например, index.html) применяется движок Jinja2:
<!DOCTYPE html>
<html>
<head><title>{{ title }};</title></head>
<body>
<ul>
{% for item in items %}
<li>{{ item }};</li>
{% endfor %}
</ul>
</body>
</html>
В Python передаётся список items: return render_template('index.html', items=['A','B','C']).
Ошибка: если переменная items не определена, Jinja2 выдаст UndefinedError. Проверяйте наличие переменных перед рендерингом.
Как обработать POST запрос с формой?
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
# проверка
return 'Успешный вход'
return render_template('login.html')
Форма должна отправляться методом POST. Данные извлекаются из request.form.
Проблема: если поле отсутствует, возникнет KeyError. Безопаснее использовать request.form.get('username') с указанием значения по умолчанию.
Как подключить SQLAlchemy для работы с базой данных?
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(50), unique=True, nullable=False)
После определения моделей выполните db.create_all() в контексте приложения для создания таблиц.
Ошибка: RuntimeError: working outside of application context возникает при вызове db.create_all() вне запроса. Используйте with app.app_context(): db.create_all().
Как разделить приложение на модули с Blueprints?
from flask import Blueprint
auth = Blueprint('auth', __name__, url_prefix='/auth')
@auth.route('/login')
def login():
return 'Страница входа'
# В главном файле:
app.register_blueprint(auth)
Blueprints позволяют структурировать крупные проекты. Каждый blueprint имеет своё пространство имён для маршрутов и шаблонов.
Проблема: циклические импорты между модулями. Решение - создание общего пакета app и инициализация Flask внутри функций (create_app фабрика приложений).
Как обработать ошибку 404 и показать свою страницу?
@app.errorhandler(404)
def not_found(e):
return render_template('404.html'), 404
Создайте шаблон 404.html в папке templates. Аналогично обрабатываются 500, 403 и другие коды.
Типичная ошибка: если не вернуть второй кортеж с кодом (404), Flask может вернуть 200. Всегда указывайте код ответа.
Часто встречающиеся ошибки и их решения
- ImportError: No module named flask - Flask не установлен. Выполните
pip install flask. - KeyError при обращении к
request.form- проверяйте метод запроса или используйтеget(). - Circular import - инициализируйте приложение через фабрику или перенесите объявление blueprints в отдельный модуль.
- TemplateNotFound - убедитесь, что шаблон лежит в папке
templatesи имя написано верно. - RuntimeError: Working outside of application context - используйте
with app.app_context():для операций с БД или g.
Расширенные примеры с пояснениями
Генерация URL с помощью url_for
Функция url_for создаёт URL по имени функции-обработчика. Это удобно для рефакторинга маршрутов.
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/profile/<int:user_id>')
def profile(user_id):
return f'User {user_id}'
with app.test_request_context():
print(url_for('profile', user_id=1))
print(url_for('profile', user_id=42))
/profile/1 /profile/42
Применение: в шаблонах для ссылок, чтобы не прописывать пути жёстко. Изменение маршрута не ломает ссылки.
Использование g для хранения данных между запросами
Объект g (global) живёт только во время одного запроса. Подходит для загрузки текущего пользователя, соединения с БД и т.д.
from flask import Flask, g, session
app = Flask(__name__)
app.secret_key = 'mysecret'
@app.before_request
def load_user():
g.user = None
if 'user_id' in session:
g.user = User.query.get(session['user_id']) # гипотетическая модель
@app.route('/dashboard')
def dashboard():
if g.user is None:
return 'Необходима авторизация', 401
return f'Добро пожаловать, {g.user.username}'
Важно: g не может храниться между разными запросами (в отличие от сессии). Не помещайте туда большие объекты.
При открытии /dashboard без сессии: "Необходима авторизация" с кодом 401.
Собственный декоратор для проверки прав (admin_required)
Декоратор позволяет защитить маршруты от неавторизованных пользователей, инкапсулируя логику проверки.
from functools import wraps
from flask import abort, g
def admin_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not g.user or not g.user.is_admin:
abort(403)
return f(*args, **kwargs)
return decorated_function
@app.route('/admin')
@admin_required
def admin_panel():
return 'Административная панель'
При попытке доступа не-администратора будет возвращена страница 403 Forbidden. Можно настроить кастомный обработчик ошибок.
Для пользователя без прав: ответ с кодом 403.
Кастомный обработчик ошибок, возвращающий JSON (для API)
Если ваше приложение предоставляет REST API, удобно возвращать JSON вместо HTML при ошибках.
@app.errorhandler(404)
def not_found_json(e):
return {'error': 'Not found', 'status': 404}, 404
@app.errorhandler(403)
def forbidden_json(e):
return {'error': 'Forbidden', 'status': 403}, 403
Теперь при 404 или 403 возвращается JSON-объект. Не забудьте установить заголовок Content-Type: application/json (Flask делает это автоматически, если вернуть dict).
При запросе к несуществующему ресурсу:
{"error": "Not found", "status": 404}
Использование Flask-Migrate для миграций базы данных
Flask-Migrate интегрирует Alembic для управления изменениями схемы. Позволяет отслеживать изменения моделей и применять их без потери данных.
# Установка: pip install flask-migrate
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
db = SQLAlchemy(app)
migrate = Migrate(app, db)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
Команды терминала:
export FLASK_APP=app.py # или set FLASK_APP=app.py на Windows
flask db init
flask db migrate -m "Создание таблицы User"
flask db upgrade
После изменений в моделях снова выполните flask db migrate и flask db upgrade.
В результате появляется папка migrations с историей изменений. База данных обновляется до последней версии.
Типичная ошибка: alembic.util.exc.CommandError при отсутствии переменной окружения FLASK_APP. Убедитесь, что она указывает на файл с объектом app.