我试图重构一个手动渲染字段的Django模板(参见https://docs.djangoproject.com/en/2.0/topics/forms/#rendering-fields-manually)。标签生成如下:
<label for="{{ field.id_for_label }}"
class="{% if field.value %}active{% endif %} {% if field.errors %}invalid{% endif %}">
</label>
使用field
... {% for field in form %}
循环{% endfor %}
。
我试图通过编写自定义过滤器来重构这一点(参见https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/#writing-custom-template-filters)。到目前为止,我已经提出以下建议。在templatetags
目录中,我添加了label_with_classes.py
,其中包含
from django import template
register = template.Library()
@register.filter(is_safe=True)
def label_with_classes(value, arg):
return value.label_tag(attrs={'class': arg})
我用
替换上面的HTML {{ field|label_with_classes:"active"}}
问题在于,这实际上并不像原始模板那样做;它总是用类"active"
标记它并且不会实现条件逻辑。
我的问题:使用过滤器可以实现这种逻辑吗?过滤函数的value
输入参数实际代表什么,是field.value
(顾名思义)还是field
本身?
答案 0 :(得分:0)
通过在开发服务器运行并刷新页面时进入调试器,我发现value
实际上是BoundField
的一个实例,它具有value()
方法, errors
属性:
> /Users/kurtpeek/Documents/Dev/lucy/lucy-web/dashboard/templatetags/label_with_classes.py(8)label_with_classes()
7 import ipdb; ipdb.set_trace()
----> 8 return value.label_tag(attrs={'class': arg})
9
ipdb> value
<django.forms.boundfield.BoundField object at 0x113957eb8>
ipdb> dir(value)
['__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__html__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'as_hidden', 'as_text', 'as_textarea', 'as_widget', 'auto_id', 'build_widget_attrs', 'css_classes', 'data', 'errors', 'field', 'form', 'help_text', 'html_initial_id', 'html_initial_name', 'html_name', 'id_for_label', 'initial', 'is_hidden', 'label', 'label_tag', 'name', 'subwidgets', 'value']
ipdb> value.errors
[]
ipdb> value.value
<bound method BoundField.value of <django.forms.boundfield.BoundField object at 0x113957eb8>>
ipdb> value.value()
4
我对变量value
的使用感到有些困惑,并改为重命名虚拟变量bound_field
。
以下是我如何实现实现条件类的自定义过滤器(在templatetags/label_with_classes.py
中):
from django import template
register = template.Library()
@register.filter(is_safe=True)
def label_with_classes(bound_field):
classes = f"{'active' if bound_field.value() else ''} {'invalid' if bound_field.errors else ''}"
return bound_field.label_tag(attrs={'class': classes.strip()})
之后可以通过
在模板中替换<label>
元素
{% load label_with_classes %}
{% for field in form %}
{{ field|label_with_classes }}
{% endfor %}