在 Django 中使用“_id”

Syg*_*gol 5 python django django-orm

当我们将 ORM 与某些使用外键的模型一起使用时,我对 Django 如何处理 '_id' 属性感到有些困惑。例如:

class CartItem(models.Model):
    user = models.ForeignKey('accounts.CustomUser', related_name='carts', on_delete=models.CASCADE, verbose_name='User')
    product = models.ForeignKey('pizza.Product', related_name='carts', on_delete=models.CASCADE, verbose_name=_('Product'))
    quantity = models.SmallIntegerField(verbose_name=_('Quantity'))
Run Code Online (Sandbox Code Playgroud)

当我将 ORM 与“过滤器”一起使用时,我可以轻松使用以下内容:

CartItem.objects.filter(user=1, product=1, quantity=1)
Run Code Online (Sandbox Code Playgroud)

Django 有点“看到”,我指的是“id”,但是当我使用完全相同的代码行,但使用“创建”而不是“过滤器”时:

CartItem.objects.create(user=1, product=1, quantity=1)
Run Code Online (Sandbox Code Playgroud)

然后它抛出一个错误说:

无法分配“1”:“CartItem.user”必须是“CustomUser”实例。

要创建它,我需要使用:

CartItem.objects.create(user_id=1, product_id=1, quantity=1)
Run Code Online (Sandbox Code Playgroud)

这是为什么?这里有什么我不明白的规则吗?

Wil*_*sem 4

这是[Django-doc]数据库表示ForeignKey。对模型对象的引用表示为:

\n\n
\n

在幕后,Django 附加"_id"到字段名称以创建其数据库列名称。在上面的示例中,Car模型的数据库表将有一manufacturer_id列。(您可以通过指定显式更改此设置db_column)但是,您的代码永远不必处理数据库列名称,除非您编写自定义 SQL。您\xe2\x80\x99将始终处理模型对象的字段名称。

\n
\n\n

所以你可以说 Django 将构建一个带有_id后缀的“双胞胎”列。此列的类型与您的目标模型的主键类型相同,因此该列将包含您使用的模型对象的主键。请注意,您可以通过指定参数to_field=…[Django-doc]使用不同的目标字段。

\n\n

ForeignKey本身并不存在于数据库中,这是 Django 的逻辑,它将使用该对象的主对象,并将其存储在默认情况下带有后缀的列中_id

\n