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?
You should save the book before setting my_page.book = book.
The behaviour you're experiencing is described by ticket 10811.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With