Django 整体错误 _id 不能为 null,外键 ID 分配
我在理解Django(版本1.6.5)在保存不同对象时是如何分配ID的方面遇到了一些问题。这里有个简单的例子:
#models.py
class Book(models.Model):
title = models.CharField(max_length=10)
class Page(models.Model):
number = models.SmallIntegerField()
book = models.ForeignKey(Book)
在保存my_page时,出现了“IntegrityError,book_id不能为NULL”的错误。不过我觉得book_id应该是存在的,因为在这个阶段已经调用了save()来保存book。
#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
虽然有一些简单的方法可以让上面的代码正常工作,但我想知道第一种方法到底哪里出了问题。我是不是漏掉了什么,还是说这是Django处理外键时的一个缺陷或限制?
3 个回答
如果一个模型里有一个 foreign key
(外键),那么在存储记录的时候,你需要提供整个 object
(对象)。举个例子,如果你想在 Page model
(页面模型)中保存一个数字和一本书的关系,你就得把 book foreign key
(书的外键)设置为一个书的对象。这是因为外键不是普通的字段,而是指向书模型的外键。
你可以这样做:
my_page = Page(title="my title", book=Book.objects.get(pk=id))
所以总结一下,你不能仅仅通过给外键传字符串来插入记录,你必须提供那个 foreign key指向的对象
。希望这能帮到你。
在你设置 my_page.book = book
之前,应该先保存书籍。
你遇到的这个问题可以在 ticket 10811 中找到相关描述。
我明白你的意思,但现在的做法似乎更清楚。my_book
只是一个 Python 对象,它的所有属性(包括 id
)都是可以改变的。所以假设用户想要的是在创建时的值,似乎更安全。
举个例子,Django 中有一种复制数据库行的方式,它涉及到重用同一个对象来表示多个模型实例。在你的情况下,可能会像这样:
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()
那么 my_page
应该指向哪本书呢?我觉得开发者要求你在这里明确说明是对的。如果 my_book
还没有保存,尝试创建 my_page
时会直接报 ValueError
错误,这也是相关问题的解决方案。