Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Integrity error _id may not be null, ForeignKey id assignment

Tags:

python

django

I'm having issues understanding the way Django (v1.6.5) assigns the id to the different objects when saving. Taking the minimal example:

#models.py

class Book(models.Model):
    title = models.CharField(max_length=10)

class Page(models.Model):
    number = models.SmallIntegerField()
    book   = models.ForeignKey(Book)

The following view throws "IntegrityError,book_id may not be NULL" when saving my_page, however I would tend to say book_id does exist since save() has been called for the book at that stage.

#view.py

my_book = Book(title="My book")

#solution1 : having my_book.save() here

my_page = Page(number = 1, book = my_book)
my_book.save()
print("book id",my_page.book.id) #book.id does exist at that point!

#solution2: my_page.book = my_book

my_page.save()   #throws the IntegrityError exception

There are some easy solutions to make the code above work but I would like to know what is wrong with the first approach. Am I missing something or is it a glitch/limitation in the way Django handles ForeignKeys?

like image 899
Ursidours Avatar asked Sep 30 '22 16:09

Ursidours


2 Answers

You should save the book before setting my_page.book = book.

The behaviour you're experiencing is described by ticket 10811.

like image 65
Alasdair Avatar answered Oct 15 '22 15:10

Alasdair


I see your point, but the current behavior seems more explicit. my_book is just a Python object, and all of its attributes (including id) can change. So it seems safer to assume that the user wants the value that exists at instantiation time.

For example, the Django idiom for copying a database row involves reusing the same object to represent more than one model instance. In your case that might look like:

my_book = Book(title="My book")
my_page = Page(number=1, book=my_book)
my_book.save()

my_book.id = None
my_book.save()  # copy the book to a new row with a new id

my_page.save()

So which book should my_page point to? I think the developers are right to require you to be explicit here. The solution to the associated ticket will be even more direct in that you will get a ValueError when trying to instantiate my_page if my_book hasn't yet been saved.

like image 43
Kevin Christopher Henry Avatar answered Oct 15 '22 17:10

Kevin Christopher Henry