gpt4 book ai didi

html - 重构手动呈现字段的 Django 表单

转载 作者:行者123 更新时间:2023-11-28 02:33:33 24 4
gpt4 key购买 nike

我正在开发一个代码库,其中包含按照 https://docs.djangoproject.com/en/2.0/topics/forms/#rendering-fields-manually 编写的表单.这是表单模板的片段,它使用 Django Widget Tweaks :

{% load widget_tweaks %}
{% csrf_token %}

<div class="row">
<div class="input-field col s12">
{{ form.session_number|add_error_class:"invalid" }}
{% if form.session_number.errors %}
<span id="{{ form.session_number.id_for_label }}-error" class="error">{{ form.session_number.errors|join:", " }}</span>
{% endif %}
<label for="{{ form.session_number.id_for_label }}"
class="{% if form.session_number.value %}active{% endif %} {% if form.name.errors %}invalid{% endif %}">
Session Number
</label>
</div>
</div>

<div class="row">
<div class="col s12">
<label for="email">Scheduled For</label>
</div>
{{ form.scheduled_for }}
</div>

{% if form.family.value %}
<input name="family" required="" id="id_family" type="hidden" value="{{ form.family.value }}" />
{% else %}
<div class="row">
<div class="input-field col s12">

{{ form.family|add_error_class:"invalid" }}
{% if form.family.errors %}
<span id="{{ form.family.id_for_label }}-error" class="error">
{{ form.family.errors|join:", " }}
</span>
{% endif %}
<label for="{{ form.family.id_for_label }}" class="{% if form.family.errors %}invalid{% endif %}">
Family
</label>
</div>
</div>
{% endif %}

<div class="row">
<div class="input-field col s12">
{{ form.expert|add_error_class:"invalid" }}
{% if form.expert.errors %}
<span id="{{ form.expert.id_for_label }}-error" class="error">
{{ form.expert.errors|join:", " }}
</span>
{% endif %}
<label for="{{ form.expert.id_for_label }}" class="{% if form.expert.errors %}invalid{% endif %}">
Expert
</label>
</div>
</div>

<div class="row">
<div class="input-field col s12">
{{ form.session_type|add_error_class:"invalid" }}
{% if form.session_type.errors %}
<span id="{{ form.session_type.id_for_label }}-error" class="error">
{{ form.session_type.errors|join:", " }}
</span>
{% endif %}
<label for="{{ form.session_type.id_for_label }}" class="{% if form.session_type.errors %}invalid{% endif %}">
Session Type
</label>
</div>
</div>

<div class="row">
<div class="input-field col s12">
{{ form.status|add_error_class:"invalid" }}
{% if form.status.errors %}
<span id="{{ form.status.id_for_label }}-error" class="error">
{{ form.status.errors|join:", " }}
</span>
{% endif %}
<label for="{{ form.status.id_for_label }}" class="{% if form.status.errors %}invalid{% endif %}">
Status
</label>
</div>
</div>

下面是表单相应部分的样子:

enter image description here

如您所见,代码远非 DRY,django.forms.Form 之间也存在耦合。类和模板:每当你在前者添加一个字段时,你需要添加一个相应的<div class="row">到模板。

我正在考虑是否使用例如 https://docs.djangoproject.com/en/2.0/ref/forms/renderers/#the-low-level-render-api 中描述的自定义渲染器重构此代码.然而,我在犹豫这是否值得,因为像 https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html 这样的博客实际上描述了如何通过手动呈现字段来获得对表单的更多控制。

我的问题是:是否有可能使用一个简单的模板(例如

)获得相同的表单“外观和感觉”
<form action="/your-name/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>

使用合适的表单渲染器?还是有其他方法可以减少此示例中的代码重复?

最佳答案

我最终仍然手动添加字段,但定义了一些自定义过滤器以减少模板中的代码重复。这是重构后相应的模板片段:

{% load widget_tweaks %}
{% load custom_errors label_with_classes %}
{% csrf_token %}

<div class="row">
<div class="input-field col s12">
{{ form.session_number|add_error_class:"invalid" }}
{{ form.session_number|custom_errors }}
{{ form.session_number|label_with_classes }}
</div>
</div>

<div class="row">
<div class="col s12">
<label for="email">Scheduled For</label>
</div>
{{ form.scheduled_for }}
</div>

{% if form.family.value %}
<input name="family" required="" id="id_family" type="hidden" value="{{ form.family.value }}" />
{% else %}
<div class="row">
<div class="input-field col s12">
{{ form.family|add_error_class:"invalid" }}
{{ form.family|custom_errors }}
{{ form.family|label_with_classes }}
</div>
</div>
{% endif %}

<div class="row">
<div class="input-field col s12">
{{ form.expert|add_error_class:"invalid" }}
{{ form.expert|custom_errors }}
{{ form.expert|label_with_classes }}
</div>
</div>

<div class="row">
<div class="input-field col s12">
{{ form.session_type|add_error_class:"invalid" }}
{{ form.session_type|custom_errors }}
{{ form.session_type|label_with_classes }}
</div>
</div>

<div class="row">
<div class="input-field col s12">
{{ form.status|add_error_class:"invalid" }}
{{ form.status|custom_errors }}
{{ form.status|label_with_classes }}
</div>
</div>

custom_errors 过滤器在 templatetags/custom_errors.py 中定义如下:

from django import template
from django.utils.safestring import mark_safe

register = template.Library()


@register.filter
def custom_errors(bound_field):
return mark_safe(f'<span id="{bound_field.id_for_label}-error" \
class="error">{", ".join(bound_field.errors)}</span>' if bound_field.errors else '')

自定义label标签在templatetags/label_with_classes.py中定义:

from django import template
from django.forms import ChoiceField, BooleanField, DateField
from titlecase import titlecase

register = template.Library()


def pretty_name(name):
"""Convert 'first_name' to 'First Name'."""
return titlecase(name.replace('_', ' '))


def should_be_active(bound_field):
'''Determine whether the field's label should have Material's "active" class added to it'''
return (bound_field.value() and not isinstance(bound_field.field, (ChoiceField, BooleanField)))\
or isinstance(bound_field.field, DateField)


@register.filter(is_safe=True)
def label_with_classes(bound_field, contents=None):
'''Extend Django's label_tag() method to provide the appropriate Materialize CSS classes'''
active = 'active' if should_be_active(bound_field) else ''
invalid = 'invalid' if bound_field.errors else ''
classes = f"{active} {invalid}".strip()
contents = contents or pretty_name(bound_field.name)
return bound_field.label_tag(attrs={'class': classes},
contents=contents,
label_suffix='')

这使代码更加简洁,也明确了各个字段“复制粘贴”背后的一些逻辑。

关于html - 重构手动呈现字段的 Django 表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48895216/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com