【问题标题】:Efficient querying of Django queryset intersection with different models高效查询 Django 查询集与不同模型的交集
【发布时间】:2016-03-29 03:44:28
【问题描述】:

我正在尝试进行稍微复杂的 Django 查询集交互,但遇到了障碍。

class A(models.Model):
    owner = models.ForeignKey(User)
    x = models.CharField(max_length=10)
    y = models.CharField(max_length=10)

class B(models.Model):
    owner = models.ForeignKey(User)
    x = models.CharField(max_length=10)
    y = models.CharField(max_length=10)

a_queryset = user.a_set.filter(x__in=("foo", "bar", "baz"))
b_queryset = B.objects.filter(???)

任何人碰巧知道一种有效的方法来生成 B 对象的查询集,这些对象与给定的 A 查询集具有相同的 x/y 对?给定任意 a_queryset 是否有快速的方法?

【问题讨论】:

    标签: django


    【解决方案1】:

    你不能使用查询集来做到这一点,因为AB 即使它们有间接关系(user 模型)你也没有使用它进行查询,所以它们之间没有关系。

    您可以使用 python 内置函数来完成。

    【讨论】:

      【解决方案2】:

      鉴于a_queryset,您可以获得(x, y) 对并使用Q objects 构建查询

      首先,从a_queryset 获取(x, y) 唯一对:

      xy_pairs = a_queryset.values_list('x', 'y').distinct()
      # [('x1', 'y1'), ('x2', 'y2'), ('x1', 'y2'), ('x2', 'y1')]
      

      对于一对('x1', 'y1'),您可以轻松搜索所有B 对象,如下所示:

      b_objs = B.objects.filter(x='x1', y='y1')
      

      但是,在这里您需要构建一个如下所示的查询:

      # (x='x1' AND y='y1') OR (x='x2' AND y='y2') .... etc.
      

      你可以通过创建Q objects来实现这一点

      # first create AND queries for different (x, y) pairs
      q_and_queries = [(Q(x=x) & Q(y=y)) for x, y in xy_pairs]
      
      #[<Q: (AND: ('x', 'x1'), ('y', 'y1'))>,
      # <Q: (AND: ('x', 'x2'), ('y', 'y2'))>,
      # <Q: (AND: ('x', 'x1'), ('y', 'y2'))>,
      # <Q: (AND: ('x', 'x2'), ('y', 'y1'))>]
      
      # then combine those queries using OR
      q_or_query = Q()
      for q in q_and_queries:
          q_or_query |= q
      
      # <Q: (OR: (AND: ), (AND: ('x', 'x1'), ('y', 'y1')), (AND: ('x', 'x2'), ('y', 'y2')), (AND: ('x', 'x1'), ('y', 'y2')), (AND: ('x', 'x2'), ('y', 'y1')))>
      

      现在,您可以使用最终查询 q_or_query 从模型 B 获取所需的查询集:

      b_queryset = B.objects.filter(q_or_query)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-19
        • 1970-01-01
        • 2012-12-15
        • 1970-01-01
        • 2020-11-14
        • 2010-09-26
        • 2011-03-19
        • 2015-06-23
        相关资源
        最近更新 更多