Как отобразить поле формы django в шаблоне
Я хочу сделать страницу со списком пользователей и флажками, которые сигнализируют, если выбран пользователь, который применит некоторые действия к выбранным пользователям. Я создал класс формы, который выглядит так:
#in forms.py
class UserSelectionForm(forms.Form):
"""form for selecting users"""
def __init__(self, userlist, *args, **kwargs):
self.custom_fields = userlist
super(forms.Form, self).__init__(*args, **kwargs)
for f in userlist:
self.fields[str(f.id)] = forms.BooleanField(initial=False)
def get_selected(self):
"""returns selected users"""
return filter(lambda u: self.fields[str(u.id)], self.custom_fields)
в моем шаблоне у меня есть пользователи, перечисленные в таблице, и я хочу, чтобы последний столбец этой таблицы был этими флажками. Мне нужно отображать поля по одному в зависимости от их имени. Я попытался создать тег шаблона, который вернул бы html-код необходимой формы элемент:
#in templatetags/user_list_tags.py
from django import template
register = template.Library()
#this is django template tag for user selection form
@register.filter
def user_select_field(form, userid):
"""
returns UserSelectionForm field for a user with userid
"""
key = std(userid)
if key not in form.fields.keys():
print 'Key %s not found in dict' % key
return None
return form.fields[key].widget.render(form, key)
наконец, вот код шаблона:
<form action="" method="post">
{% csrf_token %}
<table class="listtable">
<tr>
<th>Username</th>
<th>Select</th>
</tr>
{% for u in userlist %}
<tr>
<td>{{u.username}}</td>
<td>{{select_form|user_select_field:u.id}}</td>
</tr>
{% endfor %}
</table>
<p><input type="submit" value="make actions" /></p>
однако это не привязывает эти виджеты к форме и, таким образом, после отправки формы проверка не выполняется. В сообщении об ошибке говорится, что требуются все настраиваемые поля. Итак, вот мои вопросы:
как правильно отображать отдельные поля формы?
Как правильно создать такую форму с чекбоксами? (Я имею в виду может быть, мой метод глуп, и есть гораздо более простой способ достичь того, чего я хочу.
2 ответов
Вы делаете шаблон слишком сложный. Добавьте метку в каждое поле при его создании в форме __init__
метод.
for f in userlist:
self.fields[str(f.id)] = forms.BooleanField(label=f.username, initial=False)
тогда просто петля над полями в форме и не беспокойтесь о
Ok поэтому я думаю, что нашел способ правильно отобразить отдельные поля формы. Я нашел его, наблюдая за источниками django. Django.forms.forms.BaseForm
класс _html_output
метод, который создает экземпляр Django.forms.forms.BoundField
и затем добавляет unicode(boundField)
к выходу html. Я сделал то же самое, и это сработало отлично:
#in templatetags/user_list_tags.py
from django import template
from django import forms
register = template.Library()
#this is djangp template tag for user selection form
@register.filter
def user_select_field(form, userid):
"""
returns UserSelectionForm field for a user with userid
"""
key = str(userid)
if key not in form.fields.keys():
print 'Key %s not found in dict' % key
return None
#here i use BoundField:
boundField = forms.forms.BoundField(form, form.fields[key], key)
return unicode(boundField)
который создал тот же html, что и {{form.as_p}}, поэтому запрос POST будет выглядеть точно так же, и форма будет обработана правильно.
Я также исправил некоторые ошибки в моем класс формы:
#in UserSelectionForm definition:
...
#__init__
for f in userlist:
self.fields[str(f.id)] = forms.BooleanField(initial=False, required=False)
#get_selected
return filter(lambda u: self.cleaned_data[str(u.id)],
self.custom_fields)
теперь это работает так, как я планировал, без какого-либо javascript.