'Fieldlist' / 'FormField' неправильно рендерится с flask_wtf
Я использую списки полей в wtforms с колбой, но их значения по умолчанию не отображаются правильно.
В приведенном ниже примере Fieldlist имеет значение min_entries, равное 1, и я добавляю две дополнительные записи с помощью метода append_entry().
Две дополнительные записи отображаются неправильно, поскольку их значение больше не является значением по умолчанию, а представляет собой некрасивый текст, который смешивает html и значение по умолчанию.
На данный момент я решил вообще не использовать списки полей в своем проекте, и вместо этого я генерирую фиксированное количество записей через min_entries, что означает, что я не могу использовать динамическое количество записей.
Как колба отображает записи списка полей
Первая запись: value="[Enter track number]"
Вторая запись: value="<input id="track" name="track" type="text" value="[Enter track number]">"
Зависимости и дерево папок
- колба: 1.0.2
- Flask-Bootstrap: 3.3.7.1
- Колба-ВТФ: 0,14,2
Структура папки:
App── app.py
Templates── шаблоны
| Album── album_add.html
app.py
# Load and initialise flask variables
app = Flask(__name__)
SECRET_KEY = os.urandom(32); app.config['SECRET_KEY'] = SECRET_KEY
bootstrap = Bootstrap(app)
# form
class TrackShortList(FlaskForm):
song_index = SelectField('Select Track')
track_number = StringField('Track number', default='[Enter track number]')
def __init__(self, csrf_enabled=False, *args, **kwargs):
super(TrackShortList, self).__init__(csrf_enabled=csrf_enabled, *args, **kwargs) # required to disable csrf otherwise 'CSRF Token' is displayed
# see https://stackru.com/questions/15649027/wtforms-csrf-flask-fieldlist
class selectTracks(FlaskForm):
tracks = FieldList(FormField(TrackShortList), min_entries=1)
# route
@app.route('/addtrack', methods=['post','get'])
def addtrack():
track_select = [("Select track",)*2, ("A track",)*2, ("Another track",)*2]
form = selectTracks()
for i in range(2):
trackChildForm = TrackShortList()
form.tracks.append_entry(trackChildForm)
for sub_form in form.tracks:
sub_form.song_index.choices = track_select
if form.validate_on_submit():
pass
return render_template('album_add.html', form=form)
album_add.html
{% import "bootstrap/wtf.html" as bswtf %}
<div class='form'>
<form method="POST">
{{ form.hidden_tag() }}
{% for track_select in form.tracks %}
<tr>
{% for field in track_select %}
<td>{{ bswtf.form_field(field) }}</td>
{% endfor %}
</tr>
<hr>
{% endfor %}
</div>
1 ответ
Маршрут ниже работает.
Разница в этой линии trackChildForm.track_number = '[Enter track number]'
который я предполагаю переопределяет значение по умолчанию TrackShortList.track_number.
Я нашел это решение, посмотрев на аналогичную проблему, описанную здесь. Но я понятия не имею, почему это сработало, поэтому любые разъяснения приветствуются.
@app.route('/addtrack_working', methods=['post','get'])
def addtrack_working():
track_select = [("Select track",)*2, ("A track",)*2, ("Another track",)*2]
form = selectTracks()
for i in range(2):
trackChildForm = TrackShortList()
trackChildForm.track_number = '[Enter track number]'
form.tracks.append_entry(trackChildForm)
for sub_form in form.tracks:
sub_form.song_index.choices = track_select
if form.validate_on_submit():
pass
return render_template('album_add.html', form=form)
Класс append_entry ожидает данные, а не форму. Если данные не указаны, добавляется пустой экземпляр определенной формы.
Так что для вашего случая использования это было бы как:
track_select = [("Select track",)*2, ("A track",)*2, ("Another track",)*2]
form = selectTracks()
for i in range(2):
form.tracks.append_entry()
for sub_form in form.tracks:
sub_form.song_index.choices = track_select
if form.validate_on_submit():
pass
return render_template('album_add.html', form=form)