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)

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

Спасибо!


person David    schedule 25.05.2013    source источник


Ответы (2)


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

{# 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. ...
person Sean Vieira    schedule 26.05.2013
comment
Спасибо! Я не уверен, что понимаю ссылку на render_form - я вернулся к документации WTForms и Quickstart, но не смог ее найти. Я не могу заставить его работать в моем коде. Я понял, к чему вы клоните — вы абстрагировали свой шаблон формы даже больше, чем я думал, что мне нравится. Может быть, вы можете подробнее рассказать об этом конкретном произведении? - person David; 26.05.2013
comment
Вы можете использовать макрос jinja для рендеринга формы. См. эту суть — большая часть кода, который вы там увидите, не принадлежит мне. Функция render — это просто очень общий рендерер форм. Как указал Шон, если вы пойдете по этому маршруту, вам нужно будет передать экземпляр формы в шаблон. - person Teisman; 26.05.2013
comment
Спасибо! это помогает прояснить. - person David; 27.05.2013

Самый простой способ решить эту проблему — не включать SubmitField в форму (BookForm). Мы можем передать значение отправки формы как переменную в форму, например, submit='Update' в маршруте edit_book и submit='Add Book'.

В маршруте заполните поля сведениями, относящимися к книге, если метод публикации — «GET».

person Michael Elimu    schedule 29.11.2019