12

我想創建一個包含用戶和複選框列表的頁面,這些用戶和複選框用於指示用戶是否被選中,這將對選定的用戶應用某些操作。 我創建了一個表單類,看起來像這樣:如何在模板中呈現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> 

不過,這並不能約束這些部件的表格,因此在提交表格後,驗證失敗。錯誤消息表明所有自定義字段都是必需的。 因此,這裏是我的問題:

  1. 什麼是呈現不同的表單字段的正確方法?

  2. 用複選框創建這種表單的正確方法是什麼? (我的意思是,也許我的方法是愚蠢的,沒有達到我想要的東西更簡單的方法。

+0

也許你應該嘗試用一點javascript來做這件事。 – unni

+0

我不想在這個舞臺上的項目中使用JavaScript。但是,我應該怎麼做?或者,我應該谷歌?你知道我不是一個巨大的JavaScript專業=) –

回答

8

行,所以我想我找到了正確呈現單獨表單域的方法。我發現它看着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。

+3

閱讀[源代碼](https://github.com/django/django/blob/master/django/forms/forms.py#L108)我發現,而不是使用BoundField,更清潔做'form [key ]',你會得到相同的BoundField。 –

12

你使模板過於複雜。一個標籤添加到每個字段,當你在創建它形式的__init__方法。

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

然後剛過表單中的字段循環,不擔心userlist了。

+0

不幸的是,我不能這樣做。我簡化了我的代碼,讓這個例子更加清晰。在帶有此複選框的版本錶行中,有兩列以上,除複選框之外還有另一個小部件(「選擇方法」,我可以選擇天氣來選擇所有用戶,或者只選中複選框)。也許我應該嘗試以不同的形式分割所有這些?它將失去形式'get_selected'方法的封裝,但可以簡化任務。 –

相關問題