具有复选框的窗体 [英] Formsets with checkboxes

查看:95
本文介绍了具有复选框的窗体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想能够在页面上显示模型列表,并允许用户同时选择其中的一些。

I want to be able to show the list of models on the page, and allow the user to select a few of them at the same time.

例如,说我有一个用户选择屏幕,对于模型:

For example, say I have a user selection screen, for the model:

class User(model):
   first = # char field
   last  = # char field
   birthdate = # date

然后我想要显示用户,让他们选择其中之一:

Then I want to show the users and let them select one of them:

Please select users:
[] John  Smith   Jan, 2001
[] Mike  Davis   Feb, 2002
[] John  Doe     Dec, 2000

[Continue]

然后,此表单将被POST并处理。

This form will then get POSTed and processed.

我可以想到的一个方法是使用ModelFormset。
问题是当我尝试使用ModelFormsets显示用户时,我无法添加复选框。

One way I can think of doing it is with ModelFormset. The problem is when I try to use the ModelFormsets for displaying the users, I can't add the check-box.

我可以想到的另一种方法是创建一个表单,并在其上输出一大堆具有特定ID的复选框。然后在提交 - 迭代所有选定的复选框。不知道如何使用Django的表单。

Another way I can think of is to create a form, and output on it a whole bunch of checkboxes with a particular id. Then on submit - iterate over all selected checkboxes. Not sure how that would work with Django's forms.

欢迎任何建议。谢谢。

编辑:事实证明,通过给每个复选框一个ID(例如患者ID)在同一个名称组中,只需在POST字典中查看django视图给了我正确的需要!

Well it turns out that by giving each check box an ID (for example patient id) within the same name group and simply looking at POST dictionary in the django view gives me exactly what i need!

推荐答案

我创建了一个自定义SelectMultiple小部件,用于显示对象详细信息以及一个复选框以供选择当表单仍被称为新格式时,它仍然似乎起作用:

I created a custom SelectMultiple widget for displaying object details along with a checkbox for selection back when forms was still called newforms - it still seem to work:

from django.forms import CheckboxInput, SelectMultiple
from django.utils.encoding import force_unicode
from django.utils.html import escape
from django.utils.safestring import mark_safe

class TableSelectMultiple(SelectMultiple):
    """
    Provides selection of items via checkboxes, with a table row
    being rendered for each item, the first cell in which contains the
    checkbox.

    When providing choices for this field, give the item as the second
    item in all choice tuples. For example, where you might have
    previously used::

        field.choices = [(item.id, item.name) for item in item_list]

    ...you should use::

        field.choices = [(item.id, item) for item in item_list]
    """
    def __init__(self, item_attrs, *args, **kwargs):
        """
        item_attrs
            Defines the attributes of each item which will be displayed
            as a column in each table row, in the order given.

            Any callables in item_attrs will be called with the item to be
            displayed as the sole parameter.

            Any callable attribute names specified will be called and have
            their return value used for display.

            All attribute values will be escaped.
        """
        super(TableSelectMultiple, self).__init__(*args, **kwargs)
        self.item_attrs = item_attrs

    def render(self, name, value, attrs=None, choices=()):
        if value is None: value = []
        has_id = attrs and 'id' in attrs
        final_attrs = self.build_attrs(attrs, name=name)
        output = []
        str_values = set([force_unicode(v) for v in value]) # Normalize to strings.
        for i, (option_value, item) in enumerate(self.choices):
            # If an ID attribute was given, add a numeric index as a suffix,
            # so that the checkboxes don't all have the same ID attribute.
            if has_id:
                final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
            cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
            option_value = force_unicode(option_value)
            rendered_cb = cb.render(name, option_value)
            output.append(u'<tr><td>%s</td>' % rendered_cb)
            for attr in self.item_attrs:
                if callable(attr):
                    content = attr(item)
                elif callable(getattr(item, attr)):
                    content = getattr(item, attr)()
                else:
                    content = getattr(item, attr)
                output.append(u'<td>%s</td>' % escape(content))
            output.append(u'</tr>')
        return mark_safe(u'\n'.join(output))

示例形式:

class JobSelectionForm(forms.Form):
    jobs = forms.MultipleChoiceField(widget=TableSelectMultiple(
               item_attrs=('formatted_number', 'name', 'client', 'get_status_display')))

    def __init__(self, accessible_jobs, *args, **kwargs):
        super(JobSelectionForm, self).__init__(*args, **kwargs)
        self.fields['jobs'].choices = [(j.id, j) \
                                       for j in accessible_jobs]

使用上述表单,您可以将项目列表显示为实例化表单对象时的第一个参数。

With the above form, you would pass the list of items to be displayed as the first argument when instantiating your form object.

模板:

{% if form.jobs.errors %}{{ form.jobs.errors }}{% endif %}
<table>
<thead>
  <tr>
    <th>&nbsp;</th>
    <th>Number</th>
    <th>Name</th>
    <th>Client</th>
    <th>Status</th>
  </tr>
</thead>
<tbody>
{{ form.jobs }}
</tbody>
</table>

这篇关于具有复选框的窗体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆