django 查询模型 A 并从相关模型 B 中排除一些项目

Posted

技术标签:

【中文标题】django 查询模型 A 并从相关模型 B 中排除一些项目【英文标题】:django query model A and exclude some items from related model B 【发布时间】:2020-02-18 00:23:45 【问题描述】:

我是 Django 新手,我在 *** 上遇到了一个我没有回答的问题。 基本上,我有 2 个模型,Client 和 Order 定义如下:

class Client(models.Model):
  name = models.CharField(max_length=200)
  registration_date = models.DateTimeField(default=timezone.now)
  # ..


class Order(models.Model):
  Client = models.ForeignKey(ModelA, on_delete=models.CASCADE, related_name='orders')
  is_delivered = models.BooleanField(default=False)
  order_date = models.DateTimeField(default=timezone.now)
  # ..        

我希望我的 QuerySet clients_results 满足以下 2 个条件:

客户端对象满足一些条件(例如,它们的名称以“d”开头并且它们在 2019 年注册,但可能更复杂) 我可以使用“related_name”中定义的orders关系访问的订单对象只是满足其他条件的对象;例如,订单在过去 6 周内未交付且已完成。

我可以直接在模板中执行此操作,但我觉得这不是正确的方法。 此外,我在doc 中读到,不应将来自 Order 的 Base Manager 用于此目的。 最后,我使用 Q 和 F 找到了一个与我比较接近的 question,但最后,我会得到 order_id,而理想情况下,我想拥有整个对象。

您能告诉我解决这一需求的最佳方法吗?

非常感谢您的帮助!

【问题讨论】:

【参考方案1】:

您可能应该在此处使用Prefetch(..) object [Django-doc] 为每个Client 获取相关的未交付Orders,并将它们存储在Clients 中,但随后存储在不同的属性中,否则这可以产生混乱。

因此,您可以创建如下查询集:

from django.db.models import Prefetch
from django.utils.timezone import now
from datetime import timedelta

last_six_weeks = now() - timedelta(days=42)

clients_results = Client.objects.filter(
    name__startswith='d'
).prefetch_related(
    Prefetch(
        'orders',
        Order.objects.filter(is_delivered=False, order_date__gte=last_six_weeks),
        to_attr='nondelivered_orders'
    )
)

这将包含名称以'd' 开头的所有Clients,并且由此查询集产生的每个Client 对象都将具有属性nondelivered_orders,其中包含Orders 列表在过去 42 天内交付和订购。

【讨论】:

以上是关于django 查询模型 A 并从相关模型 B 中排除一些项目的主要内容,如果未能解决你的问题,请参考以下文章

Django 内连接查询集

获取所有相关的 Django 模型对象

两个相关模型的 Django 查询

Django - 查询:使用相关模型字段注释查询集

Django 查询模型 - GROUP BY、MIN、MAX

django中的相关模型查询