Динамически добавлять новые записи WTForms FieldList из пользовательского интерфейса

У меня есть приложение flask + wtforms, в котором я хочу, чтобы пользователи могли вводить как родительский объект, так и произвольное количество дочерних объектов. Я не уверен, как лучше всего динамически создавать новые поля ввода дочерней формы из пользовательского интерфейса.

Что у меня есть до сих пор

Ниже приведен полный рабочий пример. (Примечание: это искусственный пример выделения всех рабочих частей в одном файле .py, что делает код довольно беспорядочным. Извините.)

from flask import Flask, render_template_string from flask_wtf import FlaskForm from wtforms import FieldList, FormField, StringField, SubmitField from wtforms.validators import InputRequired # Here I’m defining a parent form, AuthorForm, and a child form, BookForm. # I’m using the FieldList and FormField features of WTForms to allow for multiple # nested child forms (BookForms) to be attached to the parent (AuthorForm). class BookForm(FlaskForm): title = StringField(‘title’, validators=[InputRequired()]) genre = StringField(‘genre’, validators=[InputRequired()]) # I’m defining a min_entry of 1 so that new forms contain a blank BookForm entry class AuthorForm(FlaskForm): name = StringField(‘name’, validators=[InputRequired()]) books = FieldList(FormField(BookForm), min_entries=1) submit = SubmitField(‘Save’) # Here’s my Jinja template html_template_string = «»» <html> <head><title>stackoverflow example</title></head> <body> <form action=»» method=»post» role=»form»> {{ form.hidden_tag() }} {{ form.name.label }} {{ form.name() }} {% for book in form.books %} <p> {{ book.title.label }} {{ book.title() }} {{ book.genre.label }} {{ book.genre() }} {{ book.hidden_tag() }} </p> {% endfor %} {{ form.submit() }} </form> </body> </html> «»» # Alright, let’s start the app and try out the forms app = Flask(__name__) app.config[‘SECRET_KEY’] = ‘secret’ @app.route(‘/’, methods=[‘GET’, ‘POST’]) def index(): form = AuthorForm() if form.validate_on_submit(): for book in form.books.data: print(book) return render_template_string(html_template_string, form=form) if __name__ == ‘__main__’: app.run()

Где я застрял

Я знаю, как создавать новые дочерние записи (записи BookForm) на стороне сервера. Я мог бы просто передать пустые словари в свою форму, и WTForms сгенерировал бы для меня входные данные:

… form = AuthorForm() form.books.append_child({}) form.books.append_child({}) form.books.append_child({}) …

Бам, теперь на моей странице есть поля ввода для трех книг, и я мог бы предварительно заполнить их данные. WTForms генерирует содержимое ввода формы перед отображением страницы. Он обрабатывает все идентификаторы, необходимые для каждого входа и т. д.

Если я хочу, чтобы пользователь мог щелкнуть кнопку и добавить новые экземпляры ввода BookForm со стороны пользователя после того, как страница была отрисована… как мне это сделать? Должен ли я сам вручную создавать поля ввода в JavaScript, используя в качестве эталона то, что было сгенерировано WTForms? Это кажется грязным и склонным к поломке или, по крайней мере, к уродливому коду.

Есть ли способ для WTForms отображать HTML для новых входных данных по мере необходимости, управляя уникальностью идентификаторов входных тегов и т. Д.? Я мог бы отправить что-то обратно на сервер, чтобы добавить пустые записи в форму и повторно отобразить страницу, но это лишило бы меня всего моего существующего пользовательского ввода, поэтому на самом деле это не работает. Этот вопрос Stackoverflow предполагает то же самое в комментариях, и то же самое возражение поднятый.

Если это должно быть сделано уродливым ручным способом, то я могу это сделать. Я просто не хочу использовать плохой подход, когда есть лучшее (и, возможно, даже официальное) решение этой проблемы.

Это в основном то, для чего был создан jquery.   —  person daveruinseverything    schedule 29.04.2019

Этот ответ делает что-то вроде того, что требуется. Клонирование соответствующих полей в js, увеличение идентификаторов и рендеринг «новой» разметки — единственный разумный способ сделать это, я думаю.   —  person daveruinseverything    schedule 29.04.2019

Источник: ledsshop.ru

Стиль жизни - Здоровье!