95

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,061
  • 6
  • 36
  • 52

7 Answers7

129
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
  • 10,731
  • 9
  • 36
  • 64
  • 4
    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
115

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
  • 8,813
  • 1
  • 18
  • 33
Akshar Raaj
  • 12,731
  • 7
  • 48
  • 43
  • 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
  • 1
    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
24
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/3.1/topics/forms/modelforms/#field-types

Diego Magalhães
  • 1,516
  • 7
  • 13
  • 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
8

You would have to add:

address = forms.CharField(required=False)
Transformer
  • 3,472
  • 1
  • 19
  • 31
Atma
  • 27,485
  • 52
  • 188
  • 288
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
  • 33,459
  • 6
  • 59
  • 67
Vishal Singh
  • 570
  • 5
  • 15
  • 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
  • 33,459
  • 6
  • 59
  • 67
Filip Savic
  • 2,268
  • 23
  • 25
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
  • 287
  • 3
  • 10