Foregin关键字段名称后跟_id

时间:2018-04-29 05:16:51

标签: django django-models

在模型中,当创建外键字段时,Django显然会创建另一个具有相同字段名称后跟_id的字段。 例如,如果我有

class Post(models.Model):
    user = models.ForeignKey(User,on_delete=models.CASCADE,default=None)
    dated = models.DateTimeField(auto_now=True)
... 

然后我将提供以下字段:

id,user,user_id,dated

我不确定为什么要添加此字段(user_id)?

后来我想在类视图中覆盖我的queryset 所以我很困惑使用哪一个(用户字段或user_id字段) :

def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.filter(user_id=self.request.user.id)

或者

def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.filter(user=self.request.user.id)

我试过了两个,两个都很好用

我的问题是:

1)创建此附加字段的目的是什么?

2)原始外键字段(我的用户)和user_id字段之间有什么区别?

3)数据库中是否有useruser_id字段?有什么意义呢?

4)每条记录中useruser_id的内容是否相同?如果是这样,那么django自动创建的这个附加字段的目的是什么?

非常感谢

1 个答案:

答案 0 :(得分:1)

Django只在数据库中为外键创建一个列。

字段与其生成的_id属性之间的区别在于,访问该字段会对相关表中的完整列集执行查询,以构建完整的相关对象。如果你想要完整的对象,请使用该字段(也可能在初始查询中使用select_related()来避免你进行N + 1次查询。)

另一方面,如果你需要的只是外键的DB级值,它通常是相关对象的主键(通常是你想要的),_id属性快捷方式适合您,并且已经拥有数据,因为它实际上是外键列中的内容。

换句话说,假设我有这样的模型:

class ModelA(models.Model):
    name = models.TextField()


class ModelB(models.Model):
    name = models.TextField()
    a_instance = models.ForeignKey(ModelA)

如果您查询ModelB,例如ModelB.objects.get(pk=12),则会收到如下查询:

SELECT id, name, a_instance_id
FROM your_app.modelb
WHERE id = 12;

注意a_instance_id是列的名称 - 它只是一个外键,它存储的所有内容都是指向ModelA实例主键的指针。如果您只需要该主键,则访问a_instance_id属性已经存在,而无需进行其他查询。但是,如果您访问a_instance字段,则可以执行另一个查询:

SELECT id, name
FROM your_app.modela
WHERE id = (whatever the value of that foreign key was);