Как визуализировать поле формы Django в шаблоне - PullRequest
12 голосов
/ 16 ноября 2011

Я хочу создать страницу со списком пользователей и флажками, которые сигнализируют, если пользователь выбран, что будет применять некоторые действия к выбранным пользователям.Я создал класс формы, который выглядит следующим образом:

#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>

Однако это не связывает этивиджеты для формы и, следовательно, после отправки формы проверка не проходит.Сообщение об ошибке говорит, что все пользовательские поля обязательны для заполнения.Итак, вот мои вопросы:

  1. Как правильно отобразить отдельные поля формы?

  2. Как правильно создать такойФорма с флажками?(Я имею в виду, может быть, мой метод глуп, и есть гораздо более простой способ достижения того, что я хочу.

Ответы [ 2 ]

13 голосов
/ 17 ноября 2011

Вы делаете шаблон слишком сложным.Добавьте метку к каждому полю при ее создании в методе __init__ формы.

for f in userlist:
    self.fields[str(f.id)] = forms.BooleanField(label=f.username, initial=False)

Затем просто зациклите поля в форме и больше не беспокойтесь о userlist.

{% for field in form %}
<tr>
    <td>{{ field.label_tag }}</td>
    <td>{{ field }}</td>
</tr>
{% endfor %}
8 голосов
/ 17 ноября 2011

Хорошо. Итак, я думаю, что нашел способ правильно отображать отдельные поля формы.Я нашел это, наблюдая за источниками джанго.Класс 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.

...