В этом уроке разберем, как обновлять сущность.
Обновление сущности
Обновление — самое сложное из всех по объему действий. С точки зрения кода новое здесь только одно — заполнение сущности данными формы: school['name'] = data['name']
. Этот процесс сильно изменится при использовании ORM, а пока мы будем проставлять каждое значение руками:
Как и в случае создания, для обновления будет два обработчика: первый выводит форму редактирования, а второй обрабатывает полученные данные.
Сперва выведем форму обновления. Для этого найдем в базе переданного пользователя и подставим его данные в форму:
Обработчик формы обновления
@app.route("/schools/<id>/edit")
def schools_edit(id):
repo = SchoolRepository()
school = repo.find(id)
errors = []
return render_template(
"schools/edit.html",
school=school,
errors=errors,
)
Шаблон обновления
<form action="{{ url_for('schools_patch', id=school.id) }}" method="post">
<div>
<label>
Название *
<input type="text" name="name" value="{{ school.name }}">
</label>
{% if errors %}
<div>{{ errors.name }}</div>
{% endif %}
</div>
<input type="submit" value="Update">
</form>
Затем добавим обработчик введенных данных. Общий порядок действий такой же как у создания - извлекаем данные,валидируем. Основное различие, что вместо создания новой записи в базе мы заменим часть данных у существующей.
Обработчик обновления
@app.route("/schools/<id>/patch", methods=["POST"])
def schools_patch(id):
repo = SchoolRepository()
school = repo.find(id)
data = request.form.to_dict()
errors = validate(data)
if errors:
return render_template(
"schools/edit.html",
school=school,
errors=errors,
), 422
# Ручное копирование данных из формы в нашу сущность
school["name"] = data["name"]
repo.save(school)
flash("School has been updated", "success")
return redirect(url_for("schools_index"))
В примере выше заменяем данные вручную, но в полноценных фреймворках этот процесс обычно упрощен. Теоретически можно сделать и так: school=data
. Но у этого подхода есть один большой недостаток. Такой способ не безопасен, так как пользователь может послать данные в обход формы, например, количество денег на счету, и изменит их значение. Эту проблему решают те же пакеты, которые предоставляют Form Builder. Обычно они сразу встроены во фреймворки.
Методы
Для изменения правильно использовать HTTP-методы PATCH или PUT. Выбор будет зависеть от того, как происходит обновление. Но HTML позволяет указывать внутри тега <form> только POST
или GET
. С точки зрения семантики HTTP, это не совсем верно. POST предназначен для создания нового. НО если посмотреть на определение обработчика выше, то там мы тоже увидим использование POST.
Почему же мы так сделали? Со своей стороны микрофреймворк Flask предоставляет лишь роутинг — он не может управлять поведением форм. Поэтому при использовании HTML-формы приходится идти на компромисс — принимать данные через POST-запрос.
Но чтобы различать создание сущности от редактирования и других операции, придется использовать маршруты, которые привязаны к соответствующим обработчикам и содержат какое-то действие в названии. Например, для обновления маршрут будет выглядеть так: /posts/id/update.
Самостоятельная работа
- Реализуйте обновление пользователей
Эталонное приложение
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.