56

How do I make certain fields in a ModelForm required=False?

If I have:

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

Or if I have:

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

Django returns:

__init__() got an unexpected keyword argument 'required'
Synthead
  • 2,162
  • 5
  • 22
  • 25
  • There's no form field type called `TextArea`, you have to use an ancestor of `Field`, probably the one called `CharField` and add a `TextArea` widget – yedpodtrzitko Jun 04 '14 at 18:45
  • Would it be possible to set the field to required=False without defining a static field and/or widget type? – Synthead Jun 04 '14 at 18:48
  • possible duplicate of [Django required field in model form](http://stackoverflow.com/questions/1134667/django-required-field-in-model-form) – Vanni Totaro Aug 05 '15 at 22:10

5 Answers5

90

following from comments. Probably yes:

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
yedpodtrzitko
  • 9,035
  • 2
  • 40
  • 42
48

you ought to add blank=True to the corresponding model

The documentation says

If the model field has blank=True, then required is set to False on the form field. Otherwise, required=True.

Also see the documentation for blank itself.

rioted
  • 1,076
  • 13
  • 24
  • 1
    This should be the accepted answer since it is what `blank` is intended for – dnaranjo Jun 29 '16 at 13:15
  • 7
    This is not always the solution: Imagine you have a field in a model that is compulsory, but you want to search for objects of that type with or without this restriction. Then you want the form to allow a search without that attribute. For instance you have colour as a required field in the model, but you might want search for objects that have a certain shape, regardless of the colour. – Jens-Erik Weber Sep 26 '16 at 18:03
  • 1
    No solution is *always the solution*. But the solution I have presented is the best practice that ought to be used unless your situation is unusual (like the one you mentioned). In that case, a separate SO question would make sense. But OP doesn't mention any such situation, the question is very general and so should be the answer. – rioted Oct 04 '16 at 11:19
  • 4
    No, this solution is special solution, It’s a very common situation that you have a model with some required fields, e. g. addresses with street, city, country all compulsory, but you want to search with a form (ModelForm) for just a part of the fields, e. g. just city and country. And I understood the OP like that. Your solution, that is very obvious for me, that you define the model fields as blank=True (sometimes in combination with null=True) works just in special cases. The general answer is the one by yedpodtrzitko. – Jens-Erik Weber Feb 09 '17 at 12:57
33

When we need to set required option on a bunch of fields we can:

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',
        )
Valery Ramusik
  • 1,473
  • 18
  • 19
  • Everything works like a charm. @SandeepBalagopal could you explain what exactly went wrong and show error? – Valery Ramusik May 08 '19 at 14:45
  • tried this and the fields did not become required. If you look into the options in modelform, modelform is not having such an option https://github.com/django/django/blob/master/django/forms/models.py#L191 – Sandeep Balagopal May 09 '19 at 06:27
  • @SandeepBalagopal, do you want to tell that people voted here https://stackoverflow.com/a/24045492/5992385 and here https://stackoverflow.com/a/1429646/5992385 are wrong – Valery Ramusik May 10 '19 at 10:27
  • 5
    I didn't notice the init method you have overriden. It works. Sorry for the mixup. – Sandeep Balagopal May 13 '19 at 05:41
  • Does anyone know why this is not a standard spec of ModelForms? – Namgyu Ho Mar 13 '20 at 07:44
  • Great solution. However, I believe that all fields in a ModelForm are required by default, so wouldn't making a selected few "required" in the constructor be redundant? What one would need would be to select the optional ones and set THEM to required = False (leaving the rest in the default state of True). – isilanes Jul 14 '20 at 09:17
  • 1
    @isilanes You sad "I believe that all fields in a ModelForm are required by default". But not all. Weather field is required on a ModelForm depends on the field parameters on its Model. And sometimes we need override such behavior by making non required field required. – Valery Ramusik Jul 15 '20 at 10:16
5

the following may be suitable

class ThatForm(ModelForm):
    text = forms.CharField(required=False, widget=forms.Textarea)
quin
  • 276
  • 1
  • 9
-16

You could try this:

class ThatForm(ModelForm):
  class Meta:
    requireds = 
    {
       'text':False,
    }

requireds must be under Meta.

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Daniel Silva
  • 95
  • 1
  • 3
  • 2
    Did you actually use this? Because I see no indication in the Django docs or source code, that this would work. – Daniel Dec 21 '17 at 09:37