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'方法的封装,但可以简化任务。 –

相关问题