带有列表

时间:2015-11-18 13:26:02

标签: python django django-queryset

所以,我有这个模型:

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

我希望用一系列颜色过滤它。例如 关于我该怎么做的任何想法?
colors = ["blue","green"]
我需要这样的东西。

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

如何修改模型以进行过滤将会有任何帮助或消息。

3 个答案:

答案 0 :(得分:2)

你可以迭代它,直到你需要数据

才会执行任何操作
products = Product.objects.all()
for color in colors:
    products = products.filter(colors__icontains=color)

答案 1 :(得分:1)

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

正确的做法是使用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

如果您想要所有红色和蓝色的产品,请按照here所述进行操作:

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]))

它没有经过测试,但它应该可以工作,如果你需要在别的地方使用它,你可以在其他类上使用queryset,保持代码干净和干燥;)

答案 2 :(得分:1)

抱歉,我没有得到您需要的逻辑操作:ANDOR。但这不是什么大不了的事。这是一个单行:

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