django 如何在笛卡尔积/列表的列表上实现QuerySet过滤器?

g6ll5ycj  于 2023-03-04  发布在  Go
关注(0)|答案(2)|浏览(119)

我想在Django中根据嵌套列表的值实现查询集过滤,例如:

titles = [ ['nike', '38', 'blue'], 
          ['nike', '38', 'grey'],
          ['adidas', '38', 'blue'], 
          ['adidas', '38', 'grey'],
          ['salmon', '38', 'blue'], 
          ['salmon', '38', 'grey'] ]

查询集为:

queryset = Product.objects.all()

你建议动态地做如下事情:

# | mark means OR
queryset.filter(attribute__title='nike').filter(attribute__title='38').filter(attribute__title='blue') |
queryset.filter(attribute__title='nike').filter(attribute__title='38').filter(attribute__title='grey') |
queryset.filter(attribute__title='adidas').filter(attribute__title='38').filter(attribute__title='blue') |
...
queryset.filter(attribute__title='salmon').filter(attribute__title='38').filter(attribute__title='grey')

如果您对数据库架构感兴趣:

moiiocjp

moiiocjp1#

通过为子列表中的每个属性重复调用filter方法,可以为每个子列表动态生成查询集,然后使用OR运算符创建所有查询集的并集:

from functools import reduce
from operator import or_

queries = []
for attributes in titles:
    query = queryset
    for attribute in attributes:
        query = query.filter(attribute__title=attribute)
    queries.append(query)
query = reduce(or_, queries)
dsf9zpds

dsf9zpds2#

从您发布的数据库模式来看,您的ORM模型看起来如何并不清楚,但是为了给予您一个概念,下面是使用Q对象实现动态过滤器的方法:

from django.db.models import Q

titles = [['nike', '38', 'blue'],
          ['nike', '38', 'grey'],
          ['adidas', '38', 'blue'],
          ['adidas', '38', 'grey'],
          ['salmon', '38', 'blue'],
          ['salmon', '38', 'grey']]

colums = ['brand', 'size', 'color']

query = Q()
for title in titles:
    subquery = Q()
    for column_name, value in zip(colums, title):
        subquery &= Q(**{column_name: value})
    query |= subquery

queryset = Product.objects.filter(Q)

为了澄清,query对象的值最终将类似于以下内容:

(OR: 
    (AND: ('brand', 'nike'), ('size', '38'), ('color', 'blue')), 
    (AND: ('brand', 'nike'), ('size', '38'), ('color', 'grey')), 
    (AND: ('brand', 'adidas'), ('size', '38'), ('color', 'blue')),
    ...
)

您可以调整columns列表中的值以适合您的模式。

相关问题