2010-11-18 36 views
4

我希望能夠在頁面上顯示模型列表,並允許用戶同時選擇其中的幾個。帶複選框的表單集

例如,說我有一個用戶選擇屏幕,爲模型:

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

然後我想告訴用戶,讓他們選擇其中之一:

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

[Continue] 

這種形式然後將被髮送並處理。

我可以想到的一種方式是使用ModelFormset。 問題是,當我嘗試使用ModelFormsets來顯示用戶時,我無法添加複選框。

我能想到的另一種方法是創建一個表單,並在其上輸出一大堆帶有特定ID的複選框。然後在提交 - 遍歷所有選中的複選框。不知道這將如何與Django的形式。

歡迎任何建議。謝謝。

編輯︰事實證明,通過給每個複選框在同一名稱組中的一個ID(例如患者ID),只是在Django視圖中查看POST字典給我正是我需要!

+0

我在這裏回答了這個問題:http://stackoverflow.com/a/27545910/1005499 – seddonym 2014-12-18 11:50:39

回答

1

您不需要表單集,因爲這是用於編輯一組模型實例中的數據。您需要的是帶有ModelChoiceFieldModelMultipleChoiceField的單一表格 - 您可能需要更改小部件才能使用CheckboxSelectMultiple

+0

的這一問題是 - 這隻能說明每個模型一個標籤。而我希望頁面顯示列「名,姓,生日」等表...雖然MultipleModelChoideField只有一個「標籤」每個模型。除非我困惑的東西? – drozzy 2010-11-18 19:42:07

+1

@drozzy:您可以使用文檔中描述的'label_from_instance()'函數來覆蓋(多個)ModelChoiceField顯示的內容。儘管如此,要將這些數據放在表中,您需要一些自定義的JS處理。 – 2010-11-18 21:46:59

+0

我不是非常渴望開始在我的python代碼中放入一些html。好吧,謝謝你的建議。 – drozzy 2010-11-19 18:31:40

3

我創建一個自定義的selectMultiple部件與用於選擇複選框一起顯示物體細節回來時,形式仍然被稱爲newforms - 它似乎仍然工作:

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] 

使用上面的表格,您可以在實例化表單對象時傳遞要作爲第一個參數顯示的項目列表。

模板:

{% 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> 
+0

謝謝,這看起來很有趣。但是,當我回答Daneil的回答時,我覺得在我的Python代碼中混合使用html真的很不舒服。 – drozzy 2010-11-23 21:15:46

+0

在這種情況下,它*應該*可以從一個自定義小部件中產生'(rendered_input_field,related_object)'的元組,但它也涉及到創建一個自定義的'BoundField'(這是你在做'{{form .fieldname}}')適當地使用小部件,而不是調用其渲染方法。 – 2010-12-02 15:40:13