79

I am using the Django REST Framework 2.0.

Here is my model class:

class Mission(models.Model):
  assigned_to = models.ForeignKey('auth.User',
                                   related_name='missions_assigned',
                                   blank = True)

Here is my view class:

class MissionList(generics.ListCreateAPIView):
    model = Mission
    serialize_class = MissionSerializer
  1. The multipart form is rendered in the browser with empty choice for assigned_to field.

  2. When posting raw JSON, I get the following error message:

Cannot assign None: "Mission.assigned_to" does not allow null values.

5 Answers 5

160

The blank option is used in the form validation, and the null is used when writing to database.

So you might add null=True to that field.

EDIT: continue the comment

Considering the two steps when saving object:

  1. Validator(controlled by blank)
  2. Database limitation(controlled by null)

For default option, take IntegerField for example,
default=5, blank=True, null=False, pass (1) even if you didn't assign a value(having blank=True), pass (2) because it has a default value(5) and writes 5 instead of None to DB.
blank=True, null=False, which pass (1) but not (2), because it attempts to write None to DB.

Thus, if you want to make a field optional, use either default=SOMETHING, blank=True, null=False or blank=True, null=True.

Another exception is the string-like field, such as CharField.
It's suggested that use the blank=True alone, leaving null=False behind.
This makes a field either a string(>=1 char(s)) or a empty string('', with len()==0), and never None.

The reason is that when null=True is set, there will be two possible value for the state "unset": empty string and None, which is confusing(and might causing bugs).

6
  • Which means blank = True must always be used with null = True? Why can't I choose empty in my form? I did use blank = True. May 16, 2013 at 13:49
  • 1
    assigned_to==None passed the form validator, but not database. Without null=True, you cannot write None into database. Thus, generally, if you want an optional field, set both blank and null to True.
    – pjw91
    May 16, 2013 at 14:11
  • 2
    However, there're two exceptions, default option and string-like fields. (I'd like to add after the post, instead of here, the comment.)
    – pjw91
    May 16, 2013 at 14:14
  • 1
    I'd just like to point out that null can also affect behaviour behind DB restrictions (see code.djangoproject.com/ticket/12708)
    – rtpg
    Oct 6, 2014 at 7:20
  • This link will be helpful for blank and null
    – Cheney
    Jun 25, 2018 at 2:28
28

ForeignKey allows null values if this behavior was set. Your code will look like this:

class Mission(models.Model):
    assigned_to = models.ForeignKey(
        'auth.User',
        related_name='missions_assigned',
        blank=True,
        null=True
    )

You have to write null=True.

Note: after you change a model, you need to run python manage.py makemigrations yourappname and then python manage.py migrate

3
  • When updating existing model it will result in error. There are some ways to get through it, the simpliest is to delete existing database. See example solution there:coderbook.com/@marcus/… Dec 4, 2019 at 19:34
  • @JakubJabłoński can you elaborate on why it will result in an error? Making a ForeignKey nullable and migrating is a common operation and should not give any error. I do that all the time. Feb 7, 2020 at 16:43
  • @JakubJabłoński You might be thinking of this for the reverse case, moving a model from "null is allowed" to "must have a value", in which case adding a manual migration to provide default values or starting from scratch, as you suggested, would be a solution. The solution discussed above, though, has no problem.
    – John Q
    Mar 3, 2020 at 20:44
8

The solution with changing the model and allowing for null with:

blank=True,
null=True

wasn't enough for me.

I was able to solve the issue by setting required in the serializer to false, e.g.

field = MyModelSerializer(required=False)

as described here (Django ForeignKey field required despite blank=True and null=True).

I ended up doing both. Allowing for null with blank=True, null=True in the model and not requiring the field in the serializer by required=False

1
  • 1
    this answer needs more upvotes. Saved me hours. Feb 27, 2022 at 15:01
2

In my case, required=False wasn't enough. I needed allow_null in the serializer, per Django ForeignKey field required despite blank=True and null=True.

1

I tried clearing my database table and I can now migrate with no errors. This also happens if there are existing rows on your table. Also don't forget to add null=True.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.