Home > Blockchain >  Django Rest Framework - filters models where ArrayField includes value1 OR value2, not subset
Django Rest Framework - filters models where ArrayField includes value1 OR value2, not subset

Time:01-13

straight to the point.

This is my model:

class Product(models.Model):

brand = models.CharField(max_length=40)
model = models.CharField(max_length=40)
price = models.FloatField(default=0)

colors = ArrayField(models.CharField(max_length=20), blank=True, null=True, default=[])
sizes = ArrayField(models.IntegerField(), blank=True, null=True)

discount_price = models.FloatField(null=True, blank=True, default=list)
date_added = models.DateTimeField(auto_now_add=True)
desc = models.TextField(default=None, blank=True, null=True)
gender = models.CharField(choices=GENDER_CHOICES, blank=True, null=True, max_length=10)
for_kids = models.BooleanField(blank=True, null=True)

Serializer:

class ProductsSerializer(serializers.ModelSerializer):

pictures = ProductPicturesSerializer(many=True, read_only=True)
average_rating = serializers.SerializerMethodField()

def get_average_rating(self, obj):
    return obj.average_rating

class Meta:
    model = Product
    fields = ['id', 'brand', 'model', 'price', 'discount_price',
              'date_added', 'for_kids', 'gender',
              'average_rating', 'sizes', 'colors', 'pictures']

My custom filter:

class CharArrayFilter(filters.BaseCSVFilter, filters.CharFilter):
    pass


class ProductsFilter(filters.FilterSet):

    min_price = filters.NumberFilter(field_name="price", lookup_expr='gte')
    max_price = filters.NumberFilter(field_name="price", lookup_expr='lte')

    colors = CharArrayFilter(lookup_expr='contains')


    class Meta:
        model = Product
        fields = {
            'brand': ['in'],
            'model': ['in', 'exact'],

        }

The problem is, when Im filtering it with colors like: red,black,blue, it only displays objects which have subset of theese values in array, not one of them which is my goal. I cant find ANY lookup expression that would work,trying lookup_expr = colors__in also doesn't work if anyone is wondering. Like display all shoes which have value red OR black OR blue in this field.

Please help, I've tried everything

CodePudding user response:

overlap is the lookup expression you are after.

Returns objects where the data shares any results with the values passed. Uses the SQL operator &&. For example:

>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])

>>> Post.objects.filter(tags__overlap=['thoughts'])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__overlap=['thoughts', 'tutorial'])
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
  •  Tags:  
  • Related