108

I have a form like this:

class My_Form(ModelForm):
    class Meta:
        model = My_Class
        fields = ('first_name', 'last_name' , 'address')

How can I set the address field as optional?

Andres
  • 4,323
  • 7
  • 39
  • 53

7 Answers7

143
class My_Form(forms.ModelForm):
    class Meta:
        model = My_Class
        fields = ('first_name', 'last_name' , 'address')

    def __init__(self, *args, **kwargs):
        super(My_Form, self).__init__(*args, **kwargs)
        self.fields['address'].required = False
madzohan
  • 11,488
  • 9
  • 40
  • 67
  • 5
    Altough the answer of akshar looks better, this method prevents you have to do stuff to set stuff like help_text and label. – Blackeagle52 Nov 24 '15 at 09:39
  • 4
    This method is especially helpful in dealing with fields which are defined as FKs at model level. By akshar's method, one would have to set the `queryset` attribute. – PritishC Jan 22 '16 at 09:55
  • Shouldn't you put `self.fields['address'].required = False` before `super(My_Form, self).__init__(*args, **kwargs)`!? – chakmeshma Sep 21 '22 at 12:41
  • 1
    @chakmeshma you won't override anything in that case =) – madzohan Dec 20 '22 at 09:56
121

Guess your model is like this:

class My_Class(models.Model):

    address = models.CharField()

Your form for Django version < 1.8:

class My_Form(ModelForm):

    address = forms.CharField(required=False)

    class Meta:
        model = My_Class
        fields = ('first_name', 'last_name' , 'address')

Your form for Django version > 1.8:

class My_Form(ModelForm):

    address = forms.CharField(blank=True)

    class Meta:
        model = My_Class
        fields = ('first_name', 'last_name' , 'address')
aronadaal
  • 9,083
  • 1
  • 19
  • 33
Akshar Raaj
  • 14,231
  • 7
  • 51
  • 45
  • 3
    What about foreign key field? – digz6666 Oct 17 '13 at 04:14
  • 18
    Use ModelChoiceField. So, if field definitions is `abc=models.ForeignKey(Abc)`, you can write `abc = forms.ModelChoiceField(queryset=Abc.objects.all(), required=False)` – Akshar Raaj Oct 17 '13 at 09:33
  • 2
    Make sure that forms is imported if you weren't using it before: `from django import forms` – Justin McCandless Oct 30 '13 at 04:11
  • 2
    Are you sure Django > 1.8 is supposed to accept `blank=True`? The docs say otherwise and my code doesn't like it, they say I should use `required=False`. Did you get your signs inverted? – Luca Bezerra Nov 27 '20 at 21:03
28
field = models.CharField(max_length=9, default='', blank=True)

Just add blank=True in your model field and it won't be required when you're using modelforms.

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

source: https://docs.djangoproject.com/en/4.1/topics/forms/modelforms/#field-types

[Edit]: Change django doc link from 3.1 to 4.1

Diego Magalhães
  • 1,704
  • 9
  • 14
  • 1
    Should be noted that if you are submitting forms manually as in `MyForm(form_data).is_valid()`, then the field must not be referenced in `form_data`. If it is included, but sent to a blank or None value, it seems it can still trigger the validation error. – Adam Starrh Jun 18 '21 at 17:11
  • @AdamStarrh I can confirm that exception – elsadek Jun 07 '23 at 13:39
8

You would have to add:

address = forms.CharField(required=False)
Transformer
  • 3,642
  • 1
  • 22
  • 33
Atma
  • 29,141
  • 56
  • 198
  • 299
6

Solution: use both blank=True, null=True.

my_field = models.PositiveIntegerField(blank=True, null=True)

Explanation:

If you use null=True

my_field = models.PositiveIntegerField(null=True)

then my_field is required, with * next to it in the form and you can't submit the empty value.

If you use blank=True

my_field = models.PositiveIntegerField(blank=True)

then my_field is not required, there won't be a * next to it in the form and you can't submit the value. But it will get null field not allowed.

Note: marking as not required and allowing null fields are two different things.

Pro Tip: Read the error more carefully than documentation.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Vishal Singh
  • 725
  • 7
  • 16
  • This answer works for fields that are not CharField or TextField. For these you do not want both null and blank because then there are multiple representations of empty. – mattm Jul 09 '21 at 22:36
5

@Anentropic's solution from the comment on @Atma's answer worked for me. And I think it's the best one too.

His comment:

null=True, blank=True will cause the ModelForm field to be required=False

I just set it on my ManyToMany field in my UserProfile class and it worked flawlessly.

My UserProfile class now looks like this (notice the friends field):

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    friends = models.ManyToManyField('self', null=True, blank=True)

I also think that this is the most beautiful solution since you do the same thing, put null and blank to True, weather you have a simple char field or, like I have, ManyToMany field.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Filip Savic
  • 2,737
  • 1
  • 29
  • 34
0

The above answers are correct; nevertheless due note that setting null=True on a ManyToManyField has no effect at the database level and will raise the following warning when migrating:

(fields.W340) null has no effect on ManyToManyField.

A good answer to this is explained in this other thread.

adriaanbd
  • 317
  • 4
  • 12