Django - 遵循外键关系(即 SQL 中的 JOIN)
Posted
技术标签:
【中文标题】Django - 遵循外键关系(即 SQL 中的 JOIN)【英文标题】:Django - Following a foreign key relationship (i.e JOIN in SQL) 【发布时间】:2010-11-16 23:01:25 【问题描述】:忙着玩 django,但似乎让我绊倒的一件事是遵循外键关系。现在,我在编写 SQL 方面有很多经验,所以我可以试一试。如果 ORM 不存在,则返回结果。
基本上这是我想要返回的 SQL 查询
Select
table1.id
table1.text
table1.user
table2.user_name
table2.url
from table1, table2
where table1.user_id = table2.id
我的模型类被定义为:
class Table1(models.Model):
#other fields
text = models.TextField()
user = models.ForeignKey('table2')
class Table2(models.Model):
# other fields
user_name = models.CharField(max_length=50)
url = models.URLField(blank=True, null=True)
我已经阅读了 django 网站上有关查询集、模型和视图的文档和参考资料。但它仍然不清楚如何做到这一点。
我还使用通用列表视图设置了 url,但想从模板的第二个表中访问 user_name 字段。我在 urls.py 和 shell 中尝试了 select_related ,但它似乎不起作用。请参阅下面的示例。
在网址中配置
url(r'^$','django.views.generic.list_detail.object_list', 'queryset': Table1.objects.select_related() ),
在外壳上
>>> a = Table1.objects.select_related().get(id=1)
>>> a.id
1
>>> a.user_name
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Table1' object has no attribute 'user_name'
所以基本上,
我做错了什么? 我错过了什么吗? 将同一查询集中两个表中的字段传递到模板的最佳方法是什么(这样可以访问两个表中的字段) 这可以通过通用视图完成吗?【问题讨论】:
哎呀,想通了感觉很傻。要在模板中包含相关字段,请执行以下操作: object.id.这样的事情应该可以工作:
u = Table1.objects.get(id=1)
print u.id
print u.user.user_name
如果你想跟随外键,你必须明确地这样做。当您从 Table1 检索对象时,您不会获得自动联接。当您访问外键字段时,您只会从 Table2 中获取一个对象,在本例中为用户
【讨论】:
谢谢伙计,这似乎奏效了。尽管根据文档, select_related 选项应该返回整个查询(包括连接)。您将如何在您的 url 配置中包含所有字段? 我还从来没有需要 select_related ——正如 freiksenet 所写的,如果您需要提高性能,它会提供。另外,为什么您需要在 url 中添加任何字段?为什么不在视图中检索所需的内容? 谢谢老兄...让它工作了。现在我感觉自己像个双胞胎!你的回答有帮助! @Issy:不要担心select_related
,除非您正在处理包含多行的大型查询。对于像您这样的 onsie-twosie 查询,给定行的所有字段都被一起提取到缓存中。【参考方案2】:
select_related() 不要将第二个表结果直接添加到查询中,它只是“加载”它们,而不是懒惰地给你。只有当您确信它可以提高您的网站性能时,您才应该使用它。要获得第二张表,您需要编写
a.user.username
在 Django 中,要获取相关表,您需要通过您设计的外键来跟踪它们。查询本身并不直接转化为 SQL 查询,因为它是“懒惰的”。它只会执行您需要的 SQL,并且仅在您需要时执行。
如果您有select_related
,SQL 将在您对a
进行原始查询时执行。但是如果你没有select_related
,那么它只会在你实际执行a.user.username
时加载DB。
【讨论】:
以上是关于Django - 遵循外键关系(即 SQL 中的 JOIN)的主要内容,如果未能解决你的问题,请参考以下文章