Search code examples
djangodjango-rest-frameworkdjango-querysetdjango-filters

filter list of objects by filtering a list of objects


I have two models ItemCategory and Item, I want to filter the list of ItemCategory by filtering is_published field of item.

class ItemCategory(models.Model):
    category_name = models.CharField(max_length=50, unique=True)
    category_image = models.ImageField(upload_to='item-category', null=True)

    def __str__(self):
        return 'category: ' + self.category_name


class Item(models.Model):
    item_name = models.CharField(max_length=50)
    item_desc = models.CharField(max_length=500, blank=True)
    price = models.FloatField()

    item_image = models.ImageField(upload_to='item-images')
    num_of_items_available = models.IntegerField()

    category_name = models.ForeignKey(ItemCategory, on_delete=models.CASCADE, null=True, related_name='items')
    is_published = models.BooleanField(default=False)

    def __str__(self):
        return 'item: ' + self.item_name

Here is my approach but didn't get any success.

class ItemCategoryView(viewsets.ViewSet):
    permission_classes = (AllowAny,)
    serializer_class = ItemCategoryListSerializer

    def list(self, request, format=None):

        queryset = ItemCategory.objects.filter(items__in=Item.objects.filter(is_published=True))

        serializer = ItemCategorySerializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

ItemCategorySerializer looks like this

class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ('pk', 'item_name', 'item_desc', 'price', 'item_image', 'num_of_items_available',
              'category_name', 'is_published')


class ItemCategorySerializer(serializers.ModelSerializer):
    items = ItemSerializer(many=True, read_only=True)

    class Meta:
        model = ItemCategory
        fields = ('pk', 'category_name', 'category_image',  'items')

Can anyone tell my how i can approach to this problem?

Edit

I have tried this two queries

queryset = ItemCategory.objects.filter(items__in=Item.objects.filter(is_published=True)) queryset = ItemCategory.objects.filter(items__is_published=True)

I think both this query work but not in the way i want. Heres how it works now.

It returns list of ItemCategory where any list of item with is_published = True. Say There are 3 categories(A, B , C) and each category has 3 list of item (A1, A2, A3, B1, B2, B3, C1, C2, C3). and let all have is_published = False except C3.

So now the query result is something like this. It returns only C Category with all the list item C1, C2, C3. which is not the desired result. I should be getting only C3 since this is the only published Item.


Solution

  • You can achieve this with filter and prefetch_related:

    queryset = ItemCategory.objects.filter(items__is_published=True).prefet‌​ch_related(Prefetch(‌​"items", queryset=Item.objects.fiter(is_published=True))