【问题标题】:Django update form according to another field formDjango根据另一个字段表单更新表单
【发布时间】:2015-07-19 16:26:56
【问题描述】:

我有以下 Django 表单:

label = forms.CharField(label="Label",
                        min_length=2,
                        max_length=100,
                        required=True,
                        widget=forms.TextInput(attrs={'class': 'form-control input-sm'}))

hour = forms.ChoiceField(label="Hour",
                         choices=choice_hour,
                         required=True,
                         widget=forms.Select(attrs={'class': 'form-control input-sm'}))

minute = forms.ChoiceField(label="Minute",
                           choices=choice_minute,
                           required=True,
                           widget=forms.Select(attrs={'class': 'form-control input-sm'}))

period = forms.MultipleChoiceField(label="Day of week",
                                   choices=choice_period,
                                   required=True,
                                   error_messages={'required': 'At least you must select one day'},
                                widget=forms.CheckboxSelectMultiple(renderer=HorizontalCheckboxRenderer))


snooze = forms.ChoiceField(label="Auto stop",
                           choices=choice_snooze,
                           required=True,
                           widget=forms.Select(attrs={'class': 'form-control input-sm'}))


mode = forms.ChoiceField(label="Mode",
                          choices=choice_mode,
                          required=True,
                          widget=forms.Select(attrs={'class': 'form-control input-sm'}))

if mode == 'music':
        webradio = forms.ModelChoiceField(queryset=Webradio.objects.all(),
                                      widget=forms.Select(attrs={'class': 'form-control input-sm'}), required=False)
    else:
        webradio = forms.ModelChoiceField(queryset=Webradio.objects.all(),
                                  widget=forms.Select(attrs={'class': 'form-control input-sm'}), required=True)

    class Meta:
        model = Alarmclock
        fields = ['label', 'hour', 'minute', 'period', 'snooze', 'mode', 'webradio']

“模式”字段表单允许知道用户想要“收音机”还是“音乐”。

当模式为“音乐”时,webradio 字段可以为空。 但是当 Mode 为 'radio' 时,必须设置 webradio 字段。

如何根据模式更新网络广播字段表单?

我尝试使用 IF 条件,但我认为找不到模式变量,webradio 字段一直是必需的。

谢谢。

【问题讨论】:

  • 您必须重写 __init__ 方法才能做到这一点。这是你的完整课程吗?
  • 不,我有一些在类顶部初始化的变量/列表/元组(choices_mode 等...)

标签: django forms field


【解决方案1】:

我想这应该可以解决问题。

class FormName(forms.ModelForm):

    label = forms.CharField(label="Label",
                            min_length=2,
                            max_length=100,
                            required=True,
                            widget=forms.TextInput(attrs={'class': 'form-control input-sm'}))

    hour = forms.ChoiceField(label="Hour",
                             choices=choice_hour,
                             required=True,
                             widget=forms.Select(attrs={'class': 'form-control input-sm'}))

    minute = forms.ChoiceField(label="Minute",
                               choices=choice_minute,
                               required=True,
                               widget=forms.Select(attrs={'class': 'form-control input-sm'}))

    period = forms.MultipleChoiceField(label="Day of week",
                                       choices=choice_period,
                                       required=True,
                                       error_messages={'required': 'At least you must select one day'},
                                    widget=forms.CheckboxSelectMultiple(renderer=HorizontalCheckboxRenderer))


    snooze = forms.ChoiceField(label="Auto stop",
                               choices=choice_snooze,
                               required=True,
                               widget=forms.Select(attrs={'class': 'form-control input-sm'}))


    mode = forms.ChoiceField(label="Mode",
                              choices=choice_mode,
                              required=True,
                              widget=forms.Select(attrs={'class': 'form-control input-sm'}))

    webradio = forms.ModelChoiceField(queryset=Webradio.objects.all(),
                                      widget=forms.Select(attrs={'class': 'form-control input-sm'}), required=True)

    class Meta:
        model = Alarmclock
        fields = ['label', 'hour', 'minute', 'period', 'snooze', 'mode', 'webradio']

    def clean_mode(self):
        mode = self.cleaned_data.get('mode')
        if mode == 'music':
            self.fields['webradio'].required = False
        return super(FormName,self).clean_mode()

它的作用基本上是根据 mode 的值随时更改 webradio 字段的 required 属性。

【讨论】:

  • 谢谢,但它不起作用。 '超级对象没有属性 clean_mode'。如果我删除这一行(返回),django 会启动,但表单会返回模式和 webradios 小部件的错误。
  • 模式小部件没有显示任何错误,这是我的错误。但是在每种情况下,webradio 小部件仍然是错误的。我想我理解“super”关键字:它调用了类本身,不是吗?保留所有字段值不是问题吗?
  • super 调用父类的方法。究竟是什么错误?代替“FormName”,您必须放置您分配给表单类的名称。
  • 对不起,我的解释很糟糕,确切的错误是即使我选择音乐,Webradio-Widget 也会在网页上显示“必填字段”。因此,webradio 字段形式不需要更改为 False..
  • 好的,看完文档,我明白为什么了。使用您的代码,发送表单时页面返回super object has no attribute clean_mode。所以,我将clean_mode 重命名为cleanmode,我认为现在它没有检测到该功能。是的,我的FormName 是正确的。
【解决方案2】:

将 webradio 字段定义为不需要,然后在 clean 方法中进行验证(clean 的目的是对相互依赖的字段进行验证)。

class Form(forms.ModelForm):

    # other fields ...

    mode = forms.ChoiceField(
        label="Mode", choices=choice_mode, required=True,
        widget=forms.Select(attrs={'class': 'form-control input-sm'})
    )
    webradio = forms.ModelChoiceField(
        queryset=Webradio.objects.all(),
        widget=forms.Select(attrs={'class': 'form-control input-sm'}),
        required=False
    )

    class Meta:
        model = Alarmclock
        fields = ['label', 'hour', 'minute', 'period', 'snooze', 'mode', 'webradio']

    def clean(self):
        mode = self.cleaned_data.get('mode')
        if mode == 'music':
            webradio = self.cleaned_data.get('webradio')
            if not webradio:
                raise forms.ValidationError({'webradio': 'Webradio field is required.'})

查看the docs了解更多详情。

请注意,此方法在 Django 1.7 中已更改:

在以前的 Django 版本中,form.clean() 需要返回已清理数据的字典。此方法可能仍会返回要使用的数据字典,但不再需要。

【讨论】:

  • 谢谢,也许更好。但是我还有另一个错误,我认为这是因为我的视图在此表单中的cleaned_data之后启动'form.is_valid()'..
  • 在我的views.py中,我在这个表单上有一个form.is_valid()。我在文档中读到“is_valid()”将通过许多“clean_***”方法,我问在另一个之前启动clean_data是否没有问题。对不起,也许不是很清楚跨度>
  • 没问题,数据已经验证过了。 clean_* 方法就像额外的验证一样工作。如果您想了解有关验证过程的更多信息,check out the docs
  • 如果答案确实解决了您的问题,请接受。
  • 对不起,我不知道为什么,现在可以了,谢谢!只是我使用使用自动 ValidationError 消息的“forms.ModelForm”,因此自定义消息不起作用。但我会阅读更多相关内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-20
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多