🐛 Типичные ошибки Flask-блока (Уроки 09–11)
⚡ Топ-3 ошибки блока Flask
- Не вызвать
db.session.commit()после add/delete — изменения не сохраняются. - Не обработать
ValidationErrorот Pydantic — сервер падает с 500 вместо 400. - Использовать
orm_mode = True(Pydantic v1) вместоConfigDict(from_attributes=True)(v2).
1. Забыть db.session.commit()
Добавление объекта через db.session.add() переводит его в состояние Pending. Без commit() изменения не попадут в базу данных.
# Неправильно
question = Question(text="Ваш вопрос?")
db.session.add(question)
# Вопрос НЕ сохранён — нет commit!
# Правильно
question = Question(text="Ваш вопрос?")
db.session.add(question)
db.session.commit() # теперь сохранён в БД
return jsonify({'id': question.id}), 201
2. Не обработать ValidationError
Если клиент прислал некорректные данные, Pydantic выбросит ValidationError. Без обработки сервер вернёт 500 Internal Server Error вместо понятного 400.
# Неправильно
@questions_bp.route('/', methods=['POST'])
def create_question():
data = request.get_json()
question_data = QuestionCreate(**data) # ValidationError не поймана!
...
# Правильно
from pydantic import ValidationError
@questions_bp.route('/', methods=['POST'])
def create_question():
data = request.get_json()
try:
question_data = QuestionCreate(**data)
except (ValidationError, TypeError) as e:
return jsonify({'error': str(e)}), 400
...
3. Использование Pydantic v1 API в v2
В Pydantic v2 изменились имена методов. Использование старого API приведёт к AttributeError или DeprecationWarning.
# Неправильно (Pydantic v1 / из лекции)
class QuestionResponse(BaseModel):
class Config:
orm_mode = True
result = QuestionResponse.from_orm(question) # AttributeError в v2
result_dict = result.dict() # deprecated в v2
# Правильно (Pydantic v2)
from pydantic import ConfigDict
class QuestionResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
result = QuestionResponse.model_validate(question) # OK
result_dict = result.model_dump() # OK
4. Blueprint не зарегистрирован в create_app
Созданный Blueprint не работает, пока не зарегистрирован в приложении. Маршруты из незарегистрированного Blueprint вернут 404.
# Неправильно — Blueprint создан, но не зарегистрирован
def create_app():
app = Flask(__name__)
# app.register_blueprint(questions_bp) — забыли!
return app
# Правильно
def create_app(config=None):
app = Flask(__name__)
if config:
app.config.from_object(config)
db.init_app(app)
app.register_blueprint(questions_bp) # обязательно!
app.register_blueprint(response_bp) # обязательно!
return app
5. Отсутствие проверки None при поиске по id
Если объект не найден, db.session.get() вернёт None. Обращение к атрибутам None вызовет AttributeError.
# Неправильно
question = db.session.get(Question, id)
return jsonify({'text': question.text}) # AttributeError если None!
# Правильно
question = db.session.get(Question, id)
if question is None:
return jsonify({'message': 'Вопрос не найден'}), 404
return jsonify({'text': question.text}), 200
6. Неправильная инициализация db (прямая вместо init_app)
При использовании Application Factory нельзя привязывать db к app напрямую на уровне модуля. Это ломает тесты и использование нескольких экземпляров приложения.
# Неправильно (из лекции — для простых случаев)
app = Flask(__name__)
db = SQLAlchemy(app) # прямая привязка
# Правильно (Application Factory)
# app/models/__init__.py
db = SQLAlchemy() # без app
# app/__init__.py
def create_app():
app = Flask(__name__)
db.init_app(app) # отложенная привязка
return app
7. Доступ к db.session вне контекста приложения
Flask-SQLAlchemy требует активного контекста приложения. Запрос вне контекста вызовет RuntimeError.
# Неправильно (вне запроса или контекста)
with app.app_context(): # обязательно при работе вне запроса
questions = Question.query.all()
# В обычных запросах контекст создаётся автоматически.
# Но при тестах или CLI-скриптах нужно явно:
with app.app_context():
db.create_all()
8. Забыть flask db init перед migrate
Команда flask db migrate завершится ошибкой, если папка migrations/ ещё не создана.
# Правильный порядок (один раз для нового проекта)
flask db init # Создаёт папку migrations/
flask db migrate -m "msg" # Создаёт файл миграции
flask db upgrade # Применяет к БД