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