Django用列表过滤过滤器



所以,我有这个模型:

class Product(models.Model):
    colors = models.TextField(max_length=150,default = 'blue,green,blue')

我想用一个颜色列表来过滤它
你知道我该怎么做吗
colors = ["blue","green"]
我需要这样的东西

products = Product.objects.filter(colors__icontains = colors)

任何关于如何修改模型以进行筛选的帮助或建议都将被取消。

由于您将颜色存储为纯文本,而不使用相关模型,因此无法使用所需的过滤器类型。

正确的方法是使用ManyToManyField:一种颜色可以有多种产品,一种产品可以有多种颜色:

class Color(models.Model):
    name = models.CharField(max_length=255)
class Product(models.Model):
    colors = models.ManyToManyField(Color, related_name='colors')

然后,你可以添加这样的颜色:

blue = Color(name='blue')
blue.save()
red = Color(name='red')
red.save()
my_product = Product()
my_product.save()
my_product.colors.add(blue)

如果你想查询所有红色或蓝色的产品,只需执行:

Product.objects.filter(colors__in=[red, blue]) # Red and blue being Color instances

如果你想要所有的产品都是红色和蓝色的,只需按照这里的描述:

Product.objects.filter(colors=red).filter(colors=blue) # Red and blue being Color instances

像这样的链接过滤器不是特别方便,所以你可能想要一个自定义的QuerySet来为你做这件事:

class AllManyToManyQuerySet(models.QuerySet):
    def filter_all_many_to_many(self, attribute, *args):
        qs = self
        for arg in args:
            qs = qs.filter(**{attribute: arg})
        return qs
class Product(models.Model):
    colors = models.ManyToManyField(Color, related_name='colors')
    objects = AllManyToManyQuerySet.as_manager()

并像这样使用:

Product.objects.all().filter_all_many_to_many('colors', red, blue) # red and blue being color instances

另一种过滤方法是:

product_list = Product.objects.filter(reduce(operator.and_, [Q(colors__name=c) for c in colors]))

它是未经测试的,但它可能会工作,如果您在其他地方需要查询集,您可以在其他类上使用它,从而保持代码的干净和DRY;)

您可以对其进行迭代,在需要数据之前不会执行任何操作

products = Product.objects.all()
for color in colors:
    products = products.filter(colors__icontains=color)

对不起,我没有得到您需要的逻辑运算:AND还是OR。但这没什么大不了的。这里有一条线:

from operator import or_, and_  # i'm not quite sure which one you actually need.
from django.db.models import Q
colors = ["blue","green"]
Product.objects.filter(reduce(or_, [Q(colors__icontains=c) for c in colors]))

但说到设计,我不能说有任何理由这样存储这些价值观。如果您出于某种原因不想使用ManyToMany,请考虑使用ArrayField

最新更新