Python Flask-WTF - использовать тот же шаблон формы для операций добавления и редактирования

Я только начинаю с Flask/Flask-WTF/SQLAlchemy, и в большинстве случаев код CRUD, который я вижу, показывает отдельные шаблоны для добавления/редактирования. Кажется, повторяется наличие двух шаблонов с почти одинаковой формой html (например, books_add.html, books_edit.html). Концептуально для меня имеет смысл иметь один шаблон, что-то вроде "books_form.html", и просто вызывать render_template на том же шаблоне из двух отдельных определений маршрутов. Я не совсем уверен, как это сделать, например:

@app.route('/books/add')
def add_book():
...
render_template('books_form.html', action = 'add')


@app.route('/books/edit/<id>')
def edit_book(id):
...
render_template('books_form.html', action = 'edit', id = id)

но я не уверен, что я на правильном пути или отклоняюсь от лучшей практики. Любой вход оценивается - конкретные мысли о том, как обрабатывать один файл шаблона, чтобы иметь дело с добавлением или редактированием поведения. Ссылки на примеры также приветствуются.

Спасибо!

Ответ 1

Нет абсолютно никаких причин иметь отдельные шаблоны для добавления и редактирования различных вещей. Рассмотрим:

{# data.html #}
<!-- ... snip ... -->
{% block form %}
<section>
<h1>{{ action }} {{ data_type }}</h1>
<form action="{{ form_action }}" method="{{ method | d("POST") }}">
{% render_form(form) %}
</form>
</section>
{% endblock form %}

Игнорировать макрос render_form работает (есть пример в документации WTForms) - он просто берет объект типа WTForms и отображает форму в неупорядоченном списке. Затем вы можете сделать следующее:

@app.route("/books/")
def add_book():
    form = BookForm()
    # ... snip ...
    return render_template("data.html", action="Add", data_type="a book", form=form)

@app.route("/books/<int:book_id>")
def edit_book(book_id):
    book = lookup_book_by_id(book_id)
    form = BookForm(obj=book)
    # ... snip ...
    return render_template("data.html", data_type=book.title, action="Edit", form=form)

Но вам не нужно ограничивать себя только книгами:

@app.route("/a-resource/")
def add_resource():
    # ... snip ...
    return render_template("data.html", data_type="a resource" ...)

# ... etc. ...