So, I have this model:
class Product(models.Model):
colors = models.TextField(max_length=150,default = 'blue,green,blue')
and i want to filter it with a list of colors for example.
Any idea on how can i do it?colors = ["blue","green"]
I need something like this.
products = Product.objects.filter(colors__icontains = colors)
Any kind of help or sugestion on how can i modify the model to filter will be apreciated .
Since you are storing colors as plain text and not using a related model, you cannot use the kind of filters you want.
The right way to do it is to use a ManyToManyField
: a color can have multiple products and a product can have multiple colors:
class Color(models.Model):
name = models.CharField(max_length=255)
class Product(models.Model):
colors = models.ManyToManyField(Color, related_name='colors')
Then, you can add colors like this:
blue = Color(name='blue')
blue.save()
red = Color(name='red')
red.save()
my_product = Product()
my_product.save()
my_product.colors.add(blue)
If you want to query all products that are red OR blue, just do:
Product.objects.filter(colors__in=[red, blue]) # Red and blue being Color instances
If you want all products that are red AND blue, just do as described here:
Product.objects.filter(colors=red).filter(colors=blue) # Red and blue being Color instances
Chaining filters like this is not especially convenient, so you'll probably want a custom QuerySet
that will do it for you :
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()
And use it like this:
Product.objects.all().filter_all_many_to_many('colors', red, blue) # red and blue being color instances
Another filter method is:
product_list = Product.objects.filter(reduce(operator.and_, [Q(colors__name=c) for c in colors]))
It's untested, but it should probably work, and you can use the queryset on other classes if you need it elsewhere, keeping you code clean and DRY ;)
You could just iterate over it, nothing gets executed till you require the data
products = Product.objects.all()
for color in colors:
products = products.filter(colors__icontains=color)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With