我如何指定表单中字段的顺序? [django-crispy-forms]

问题描述 投票:0回答:2

我们将Django 2.1用于Speedy Net。我们有一个联系表格,最近,垃圾邮件发送者已使用该表格向我们发送垃圾邮件。我决定在表单中添加一个“ no_bots”字段,以防止机器人成功提交表单。我检查了表格,它可以正常工作,但是问题是我们有2个站点-一个站点(Speedy Net)的字段顺序正确,而另一个站点(Speedy Match)的字段顺序不正确- “ no_bots”字段位于“ message”字段之前,但我希望它是最后一个字段。我如何使它持久?我们的模板标记仅包含{% crispy form %},我在class Meta中定义了字段的顺序:

class FeedbackForm(ModelFormWithDefaults):
    ...
    no_bots = forms.CharField(label=_('Type the number "17"'), required=True)

    class Meta:
        model = Feedback
        fields = ('sender_name', 'sender_email', 'text', 'no_bots')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelperWithDefaults()
        if (self.defaults.get('sender')):
            del self.fields['sender_name']
            del self.fields['sender_email']
            del self.fields['no_bots']
            self.helper.add_input(Submit('submit', pgettext_lazy(context=self.defaults['sender'].get_gender(), message='Send')))
        else:
            self.fields['sender_name'].required = True
            self.fields['sender_email'].required = True
            self.helper.add_layout(Row(
                Div('sender_name', css_class='col-md-6'),
                Div('sender_email', css_class='col-md-6'),
            ))
            self.helper.add_input(Submit('submit', _('Send')))

    def clean_text(self):
        text = self.cleaned_data.get('text')
        for not_allowed_string in self._not_allowed_strings:
            if (not_allowed_string in text):
                raise ValidationError(_("Please contact us by e-mail."))
        return text

    def clean_no_bots(self):
        no_bots = self.cleaned_data.get('no_bots')
        if (not (no_bots == "17")):
            raise ValidationError(_("Not 17."))
        return no_bots

Speedy NetSpeedy Match

顺便说一句,我检查了我们的登台服务器,这是相反的-字段顺序在快速匹配中是正确的,但在快速网络中是不正确的。这很奇怪,因为它们都使用相同的代码!我认为这意味着字段的顺序是随机的。

更新:我删除了生产服务器上的所有* .pyc文件,现在两个站点中的字段顺序都是正确的。我还删除了登台服务器上的这些文件,现在两个站点中的字段顺序都不正确。我在登台服务器上再次执行此操作,并且其中一个站点中的字段顺序再次更改。

python django django-crispy-forms
2个回答
1
投票

原因:遍历无序集合

[crispy_formsFormHelper.render_layout这样做:

fields = set(form.fields.keys())
left_fields_to_render = fields - form.rendered_fields
for field in left_fields_to_render:
    ...

此时,left_fields_to_renderset{'text', 'no_bots'}

set是无序集合。

有时返回False[a for a in {'text', 'no_bots'}] == ['text', 'no_bots']

您可以通过打开几个不同的Python解释器实例来进行尝试-我注意到它通常在Python解释器实例中是一致的。

修复:遍历列表

基本:

fields = tuple(form.fields.keys())
left_fields_to_render = list_difference(fields, form.rendered_fields)
for field in left_fields_to_render:
    ...

我已提交PR以获得更完整的django-crispy-forms/django-crispy-forms#952修复程序。

解决方法:在布局中明确指定字段

可以说,如果未设置render_unmentioned_fields = True,则布局的预期用途。

您已经为四个字段中的两个调用了self.helper.add_layout;你可以一直走下去:

self.helper.add_layout(MultiWidgetField(
    Row(
        Div('sender_name', css_class='col-md-6'),
        Div('sender_email', css_class='col-md-6'),
    ),
    'text',
    'no_bots',
))

0
投票

您是否尝试过使用Layout方法?

从文档中:

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Fieldset, ButtonHolder, Submit

class ExampleForm(forms.Form):
    [...]
    def __init__(self, *args, **kwargs):
        super(ExampleForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Fieldset(
                'first arg is the legend of the fieldset',
                'like_website',
                'favorite_number',
                'favorite_color',
                'favorite_food',
                'notes'
            ),
            ButtonHolder(
                Submit('submit', 'Submit', css_class='button white')
            )

https://django-crispy-forms.readthedocs.io/en/latest/layouts.html#fundamentals

© www.soinside.com 2019 - 2024. All rights reserved.