Django - 跟踪外键关系(即 SQL 中的 JOIN)
我最近在玩 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 中尝试了 select_related,也在命令行中试过,但似乎都不管用。下面是一些例子。
在 urls 中的配置:
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'
所以,基本上,
- 我哪里做错了?
- 我是不是漏掉了什么?
- 在同一个查询集中,如何将两个表的字段传递到模板中(这样就可以访问两个表的字段)?
- 这可以用通用视图来实现吗?
2 个回答
2
select_related() 并不是直接把第二个表的数据加到查询里,它只是“加载”了这些数据,而不是懒懒地给你。你只有在确定它能提升你网站性能的时候才应该使用它。要获取第二个表的数据,你需要写
a.user.username
在 Django 中,要获取相关的表,你需要通过你设计的外键来跟踪它们。查询本身并不会直接转换成 SQL 查询,因为它是“懒惰”的。它只会在你需要的时候,执行你需要的 SQL。
如果你使用了 select_related
,那么在你对 a
进行原始查询时,SQL 就会被执行。但如果你没有使用 select_related
,那么数据库只会在你实际执行 a.user.username
时才会加载数据。
4
像这样应该可以工作:
u = Table1.objects.get(id=1)
print u.id
print u.user.user_name
如果你想要使用外键(就是表与表之间的关联),你必须明确地去做。也就是说,当你从表1获取一个对象时,并不会自动连接到表2。只有当你访问外键字段时,比如这个例子中的用户,才会得到表2中的对象。