简体   繁体   English

如何在模板中渲染django表单字段

[英]How to render django form field in template

I want to make a page with a list of users and checkboxes that signal if a user is selected, which will apply some action to selected users. 我想创建一个页面,其中包含用户列表和复选框,表示是否选择了用户,这将对选定的用户应用某些操作。 I created a form class which looks like this: 我创建了一个表单类,如下所示:

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

In my template I have users listed in a table and I want the last column of this table to be those checkboxes. 在我的模板中,我在表中列出了用户,我希望此表的最后一列是那些复选框。 I need to render fields one by one depending on their name. 我需要根据名称逐个渲染字段。 I tried creating a template tag that would return the html code of the needed form element: 我尝试创建一个模板标签,它将返回所需表单元素的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)

Finally, here's the template code: 最后,这是模板代码:

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

However, this does not bind those widgets to the form and thus, after submitting the form, validation fails. 但是,这不会将这些小部件绑定到表单,因此,在提交表单后,验证将失败。 The error message says that all the custom fields are required. 错误消息表明所有自定义字段都是必需的。 So here are my questions: 所以这是我的问题:

  1. What is the right way to render separate form fields? 渲染单独表单字段的正确方法是什么?

  2. What is the right way of creating such a form with checkboxes? 使用复选框创建此类表单的正确方法是什么? (I mean maybe my method is stupid and there is a much easier way of achieving what I want. (我的意思是,我的方法可能很愚蠢,有一种更容易实现我想要的方法。

You're making the template far too complicated. 你让模板太复杂了。 Add a label to each field when you create it in the form's __init__ method. 在表单的__init__方法中创建标签时,为每个字段添加标签。

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

Then just loop over the fields in the form and don't worry about the userlist anymore. 然后刚过表单中的字段循环,不担心userlist了。

{% for field in form %}
<tr>
    <td>{{ field.label_tag }}</td>
    <td>{{ field }}</td>
</tr>
{% endfor %}

Ok So I think I have found a way to correctly render separate form fields. 好吧我想我已经找到了一种正确渲染单独表单字段的方法。 I found it watching django sources. 我发现它看着django的来源。 Django.forms.forms.BaseForm class has _html_output method which creates an instance of Django.forms.forms.BoundField and then adds unicode(boundField) to the html output. Django.forms.forms.BaseForm类有_html_output它创建的实例方法Django.forms.forms.BoundField ,然后添加unicode(boundField)到HTML输出。 I did the exact same thing and it worked perfectly: 我做了完全相同的事情,它完美地工作:

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

That generated the same html as {{form.as_p}}, so the POST request will look exactly the same and form will be processed correctly. 这生成了与{{form.as_p}}相同的html,因此POST请求看起来完全相同,表单将被正确处理。

I also fixed some mistakes in my form class: 我还修复了表单类中的一些错误:

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

That now seems to work as I planned, without any javascript. 现在似乎按照我的计划工作,没有任何JavaScript。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM