如何在 Django 中过滤加入的模型?

Posted

技术标签:

【中文标题】如何在 Django 中过滤加入的模型?【英文标题】:How to filter joined models in Django? 【发布时间】:2018-07-19 00:38:58 【问题描述】:

我有以下型号:

class Street(models.Model):
    name = models.CharField(max_length=40)

class House(models.Model):
    street = models.ForeignKey(Street, models.PROTECT)
    number = models.CharField(max_length=10)

    class Meta:
        unique_together = ('street', 'number')

class Room(models.Model):
    house = models.ForeignKey(House, models.PROTECT)
    number = models.CharField(max_length=10)

    class Meta:
        unique_together = ('house', 'number')

我已经知道Street 的 ID,并且想获得那条街上所有房屋的所有房间。在 SQL 中很简单:

SELECT *
FROM room JOIN house ON house.id = room.house_id
WHERE house.street_id = xyz;

现在我如何在 Django 中做到这一点?我试过了

Room.objects.select_related('house').filter(street=xyz)

但我收到一个异常,说我无法访问此字段:

django.core.exceptions.FieldError: Cannot resolve keyword 'street' into field. Choices are: house, house_id, id, number

由于我面临的数据量很大,我真的希望能够使用单个查询进行连接和过滤!当放弃其中一个时,我将不得不求助于进行多个查询或在 Python 中进行过滤,这两者本质上都是低效的。我猜另一种方法是原始查询...

【问题讨论】:

filtering across relationships 上有一整段文档。 【参考方案1】:

您可以使用__ 语法访问相关对象的字段:

Room.objects.select_related('house').filter(house__street=xyz)

这可以根据您的需要尽可能多地完成,要按街道名称选择房间,您可以这样做:

Room.objects.select_related('house').filter(house__street__name=xyz)

查看详细信息here。

【讨论】:

注意,您不需要select_related 来使过滤器在连接模型上工作。 酷。我完全错过了文档中最明显的部分。即使是左外连接也能像魅力一样工作! @DanielRoseman 我是否也将相关连接放入select_related 是否真的很重要?它会选择不必要的字段吗? @purefanatic slect_related 允许您一次查询获取相关对象的数据。如果您不需要房子的详细信息,您可以删除 select_related。在这种情况下,filter(house__street=xyz) 也可以使用。但是,如果您稍后在代码中使用room.house,它将再次影响数据库。更多详情:docs.djangoproject.com/en/2.0/ref/models/querysets/…

以上是关于如何在 Django 中过滤加入的模型?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用标准 django 过滤器访问加入“中间”表?

如何在 django 中进行复杂的搜索?使用视图还是模型?

如何在 django 的单个视图中显示多个 ForeignKey 过滤项目?

如何在 Django 数据库请求中进行数学过滤?

如何根据Django中相同模型的其他字段ID过滤字段值

如何在 Django 模型中存储每个月的数据