Django:使模型表单中的某些字段required=False

58

如何使ModelForm中的某些字段required=False?

如果我有以下代码:

class ThatForm(ModelForm):
  class Meta:
    widgets = {"text": Textarea(required=False)}

或者如果我有:

class ThatForm(ModelForm):
  text = Textarea(required=False)

Django返回:

__init__() got an unexpected keyword argument 'required'

没有名为 TextArea 的表单字段类型,您必须使用 Field 的祖先,可能是称为 CharField 的字段,并添加一个 TextArea 小部件。 - yedpodtrzitko
有没有可能在不定义静态字段和/或小部件类型的情况下将字段设置为required=False? - Synthead
5个回答

92

根据评论,可能是的:

class ThatForm(ModelForm):
    def __init__(self, *args, **kwargs):
        # first call parent's constructor
        super(ThatForm, self).__init__(*args, **kwargs)
        # there's a `fields` property now
        self.fields['desired_field_name'].required = False

@User 我不确定,但也许官方的Django文档可以提供帮助:https://docs.djangoproject.com/en/2.1/ref/forms/fields/ - yedpodtrzitko

49

你需要在相应的模型上添加blank=True

文档中提到

如果该模型字段具有blank=True,则表单字段上的required属性将设置为False。否则,required属性将被设置为True。

另请参阅空白字段的文档


2
这应该是被接受的答案,因为它是 blank 的预期用途。 - dnaranjo
7
这不总是解决方案:想象一下,您的模型中有一个强制性字段,但您希望可以在有或没有此限制的情况下搜索该类型的对象。然后,您希望表单允许在没有该属性的情况下进行搜索。例如,您的模型中颜色是必填字段,但您可能希望搜索具有特定形状的对象,而与颜色无关。 - Jens-Erik Weber
2
没有解决方案是“永远的解决方案”。但我提出的解决方案是最佳实践,除非你的情况不寻常(比如你提到的那种情况)。在这种情况下,提出一个单独的SO问题是有意义的。但OP没有提到任何这样的情况,问题非常普遍,因此答案也应该是普遍的。 - rioted
4
不,这个解决方案是特殊的解决方案。经常会出现这样一种情况:你有一个带有一些必填字段的模型,比如街道、城市、国家等都是必填的,但你只想用一个表单(ModelForm)来搜索其中的一部分字段,比如只搜索城市和国家。我理解OP的意思就是这样。对我来说非常明显的你的解决方案是将模型字段定义为空(blank=True)(有时与null=True组合使用),但这仅适用于特定情况。一般的答案应该是yedpodtrzitko提供的那个。 - Jens-Erik Weber

34

当我们需要在一组字段上设置必填选项时,我们可以:

class ThatForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        for field in self.Meta.required:
            self.fields[field].required = True

    class Meta:
        model = User
        fields = (
            'email',
            'first_name',
            'last_name',
            'address',
            'postcode',
            'city',
            'state',
            'country',
            'company',
            'tax_id',
            'website',
            'service_notifications',
        )
        required = (
            'email',
            'first_name',
            'last_name',
            'address',
            'postcode',
            'city',
            'country',
        )

一切都像魔法般运作。@SandeepBalagopal,你能解释一下到底出了什么问题并显示错误吗? - Valery Ramusik
尝试过这个方法,但字段并没有变成必填项。如果你查看modelform中的选项,你会发现它没有这样的选项。https://github.com/django/django/blob/master/django/forms/models.py#L191 - Sandeep Balagopal
5
我没有注意到你重写了初始化方法。它有效。对于混淆感到抱歉。 - Sandeep Balagopal
有人知道为什么这不是ModelForms的标准规范吗? - Namgyu Ho
1
@isilanes,你说:“我相信ModelForm中所有字段默认都是必填的。”但并非如此。在ModelForm中,某个字段是否为必填字段取决于其在Model中的参数。有时我们需要通过将非必填字段设置为必填字段来覆盖这种行为。 - Valery Ramusik
显示剩余2条评论

5
以下内容可能适用:
class ThatForm(ModelForm):
    text = forms.CharField(required=False, widget=forms.Textarea)

-16
你可以尝试这个:
class ThatForm(ModelForm):
  class Meta:
    requireds = 
    {
       'text':False,
    }

必须将所需内容放在元数据下面。


2
你真的使用过这个吗?因为我在Django文档或源代码中没有看到任何迹象表明它会起作用。 - Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接