🐛 Типичные ошибки: Flask-проект
⚡ Топ-3 ошибки
- Забыть
db.session.commit()— изменения не сохранятся. - Зарегистрировать Blueprint без
url_prefix— маршруты конфликтуют. - Circular import: импортировать
dbиз модуля, который сам импортирует модели.
1. Забытый db.session.commit()
Неправильно
question = Question(text="Новый вопрос")
db.session.add(question)
# commit() забыт!
return jsonify({"id": question.id})
Правильно
question = Question(text="Новый вопрос")
db.session.add(question)
db.session.commit() # сохраняет изменения в БД
return jsonify({"id": question.id})
Последствие: объект добавлен в сессию, но не сохранён в базу данных. После перезапуска приложения данные исчезнут. Кроме того, question.id может быть None до commit.
2. Blueprint без url_prefix — конфликт маршрутов
Неправильно
# questions_bp.route('/questions')
# responses_bp.route('/responses')
# Регистрация БЕЗ префикса:
app.register_blueprint(questions_bp)
app.register_blueprint(responses_bp)
Правильно
app.register_blueprint(questions_bp, url_prefix='/questions')
app.register_blueprint(responses_bp, url_prefix='/responses')
Последствие без префикса: если в Blueprint маршруты определены как /, то все Blueprint будут отвечать на один URL, и Flask выдаст ошибку или последний Blueprint перекроет предыдущий.
3. Circular import — циклический импорт
Неправильно
# app/__init__.py
from flask_sqlalchemy import SQLAlchemy
from app.models.questions import Question # импорт здесь
db = SQLAlchemy()
# app/models/questions.py
from app import db # импортирует app/__init__.py
# который пытается импортировать Question
# ЦИКЛ!
Правильно
# app/__init__.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy() # db определён здесь
def create_app():
app = Flask(__name__)
db.init_app(app)
from app.routers.questions import questions_bp # импорт ВНУТРИ функции
app.register_blueprint(questions_bp, url_prefix='/questions')
return app
# app/models/questions.py
from app import db # безопасно — db уже определён, create_app не вызван
Решение: импортировать blueprints внутри функции create_app(), после инициализации расширений.
4. Инициализация db вне Application Context
Ошибка
RuntimeError: No application found. Either work inside
a view function or push an application context with
app.app_context().
# Попытка создать таблицы без контекста:
from app import db
db.create_all() # ошибка!
Правильно
from app import create_app, db
app = create_app()
with app.app_context():
db.create_all() # внутри контекста — работает
Flask-расширения требуют активного контекста приложения для работы с БД.
5. Возврат Python-объекта вместо jsonify
Неправильно
@questions_bp.route('/')
def list_questions():
questions = db.session.scalars(select(Question)).all()
return questions # TypeError: объект SQLAlchemy не сериализуем
Правильно
@questions_bp.route('/')
def list_questions():
questions = db.session.scalars(select(Question)).all()
result = [QuestionOut.model_validate(q).model_dump() for q in questions]
return jsonify(result)
ORM-объекты нельзя передавать напрямую в ответ. Нужно сериализовать через Pydantic или вручную создать словарь.
6. Дублирование имён Blueprint
Неправильно
questions_bp = Blueprint('api', __name__)
responses_bp = Blueprint('api', __name__) # то же имя!
# ValueError: The name 'api' is already registered
Правильно
questions_bp = Blueprint('questions', __name__)
responses_bp = Blueprint('responses', __name__) # уникальные имена
7. request.get_json() возвращает None
Ошибка
# При вызове POST без заголовка Content-Type: application/json
data = request.get_json()
data['text'] # TypeError: 'NoneType' object is not subscriptable
Правильно
data = request.get_json()
if not data:
return jsonify({"error": "JSON body required"}), 400
# Или с silent=False для явной ошибки:
data = request.get_json(force=True, silent=False)
Всегда проверяйте, что клиент передал Content-Type: application/json и тело не пустое.