Django按ManyToMany关系的一个值过滤并按另一个值排序

时间:2018-06-22 00:42:24

标签: python django django-models many-to-many

我有模特:

class A(models.Model):
    pass

class B(models.model):
    a = models.ForeighKey(A)
    name = models.CharField()
    value = models.CharField()

我需要获取A的X个(例如X = 10),如果B.name =='name1',则按B.value过滤,如果B.name =='name2',则按B.value排序仅使用Django ORM。

我想要的SQL是这样的:

SELECT table_a.id
  FROM table_a
  INNER JOIN table_b ON (table_a.id = table_b.a_id)
  LEFT OUTER JOIN (
      SELECT table_a.id as id, table_b.value as value
      FROM table_a
      INNER JOIN table_b ON (table_a.id = table_b.a_id)
      WHERE table_b.name = 'name2'
      GROUP BY table_a.id
  ) tmp_table ON (tmp_table.id = table_a.id)
  WHERE (table_b.name = 'name1' AND table_b.value::text LIKE '%mid%')
  GROUP BY table_a.id
  ORDER BY tmp_table.value
  LIMIT 10;

对于A的每个项目,B.name的值都是唯一的(这就是我使用INNER JOIN的原因)。

我知道的最简单的方法是:

# Filtering A
a_set = dict((a.id, {'b': {}}) for a in A.objects.filter(b__name='name1', b__value__contains='mid'))

# I just need to know all b-items for a_set
# "a_id__in=<huge list>" is bad idea, so I want to paginate a_set before it
for b in B.objects.filter(a_id__in=a_set):
    a_set[b.a_id]['b'][b.name] = b.value

# Sorting where items of A without 'name2' will be at the end
sorted_ids = list(x[1] for x in sorted(
    (a_set[a_id]['b'].get('name2', 'zzz'), a_id) for a_id in a_set
))

# Pagination
sorted_ids = sorted_ids[:10]

但是我需要针对有很多A项的情况进行优化。

0 个答案:

没有答案