当我定义类似于这样的Django表单类时:
def class MyForm(forms.Form): check = forms.BooleanField(required=True, label="Check this")
它扩展为HTML,如下所示:
我希望复选框输入元素在复选框后面有一个标签,而不是相反.有没有办法说服Django这样做?
[编辑]
感谢Jonas的回答 - 仍然,虽然它解决了我问的问题(复选框标签呈现在复选框的右侧),但它引入了一个新问题(所有窗口小部件标签都呈现在他们的窗口小部件的右侧......)
我想避免重写_html_output(),因为它显然不是为它而设计的.我想出的设计是在Field类中实现字段html输出方法,覆盖Boolean字段的方法,并在_html_output()中使用该方法.遗憾的是,Django开发人员选择采用不同的方式,我希望尽可能在现有框架内工作.
CSS听起来像一个不错的方法,除了我不知道足够的CSS来解决这个问题,甚至不知道我是否喜欢这种方法.此外,我更喜欢仍然类似于最终输出的标记,至少在渲染顺序中.
此外,由于为任何特定标记设置多个样式表是合理的,因此在CSS中执行此操作可能意味着必须多次对多个样式执行此操作,这几乎使CSS成为错误的答案.
[编辑]
好像我正在回答下面的问题.如果有人有更好的想法如何做到这一点,不要害羞.
这是我提出的解决方案(Django v1.1):
{% load myfilters %} [...] {% for field in form %} [...] {% if field.field.widget|is_checkbox %} {{ field }}{{ field.label_tag }} {% else %} {{ field.label_tag }}{{ field }} {% endif %} [...] {% endfor %}
您需要创建一个包含以下内容的自定义模板标记(在此示例中为"myfilters.py"文件):
from django import template from django.forms.fields import CheckboxInput register = template.Library() @register.filter(name='is_checkbox') def is_checkbox(value): return isinstance(value, CheckboxInput)
可用自定义模板标签更多信息在这里.
编辑:本着求问者自己的答案:
好处:
没有CSS的未来.
标记最终看起来应该如此.
我没有破解Django内部.(但不得不看一堆)
该模板很好,紧凑和惯用.
无论标签和输入字段名称的确切值如何,过滤器代码都会很好.
缺点:
可能在某处某处可以做得更好更快.
不太可能的是,客户愿意为此花费的所有时间付费,只是为了将标签移到右边......
我从romkyns那里得到了答案并使它更加通用
def field_type(field, ftype): try: t = field.field.widget.__class__.__name__ return t.lower() == ftype except: pass return False
这样,您可以直接使用字符串检查窗口小部件类型
{% if field|field_type:'checkboxinput' %} {% else %} {{ field }} {% endif %}
所有呈现的解决方案都涉及模板修改,这些修改通常在性能方面相当低效.这是一个完成工作的自定义小部件:
from django import forms from django.forms.fields import BooleanField from django.forms.util import flatatt from django.utils.encoding import force_text from django.utils.html import format_html from django.utils.translation import ugettext as _ class PrettyCheckboxWidget(forms.widgets.CheckboxInput): def render(self, name, value, attrs=None): final_attrs = self.build_attrs(attrs, type='checkbox', name=name) if self.check_test(value): final_attrs['checked'] = 'checked' if not (value is True or value is False or value is None or value == ''): final_attrs['value'] = force_text(value) if 'prettycheckbox-label' in final_attrs: label = _(final_attrs.pop('prettycheckbox-label')) else: label = '' return format_html('', attrs['id'], flatatt(final_attrs), label) class PrettyCheckboxField(BooleanField): widget = PrettyCheckboxWidget def __init__(self, *args, **kwargs): if kwargs['label']: kwargs['widget'].attrs['prettycheckbox-label'] = kwargs['label'] kwargs['label'] = '' super(PrettyCheckboxField, self).__init__(*args, **kwargs) # usage in form class MyForm(forms.Form): my_boolean = PrettyCheckboxField(label=_('Some label'), widget=PrettyCheckboxWidget())
我在一个额外的文件中有PrettyCheckboxWidget和PrettyCheckboxField,因此可以在需要时导入它们.如果您不需要翻译,则可以删除ugettext部分.此代码适用于Django 1.5,未经测试用于较低版本.
好处:
高性能,无需模板修改
易于用作自定义小部件
缺点:
"as_table"在第二列中呈现复选框+标签
模板内的{{field.label}}为空.而是将标签绑定到{{field}}
在星期六做的工作比我计划的要多;-)