Django 通过过滤对象列表来过滤对象列表

Django 通过过滤对象列表来过滤对象列表,django,django-rest-framework,django-queryset,django-filters,Django,Django Rest Framework,Django Queryset,Django Filters,我有两个模型ItemCategory和Item,我想通过过滤Item的is_published字段来过滤ItemCategory的列表 class ItemCategory(models.Model): category_name = models.CharField(max_length=50, unique=True) category_image = models.ImageField(upload_to='item-category', null=True) d

我有两个模型ItemCategory和Item,我想通过过滤Item的is_published字段来过滤ItemCategory的列表

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
这是我的方法,但没有取得任何成功

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看起来像这样

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')
有人能告诉我如何解决这个问题吗

编辑

我试过这两个问题

queryset=itemcegory.objects.filter(items\uu in=Item.objects.filter(is\u published=True))queryset=itemcegory.objects.filter(items\uu is\u published=True)

我认为这两个查询都可以,但不是我想要的方式。这就是它现在的工作原理

它返回ItemCategory列表,其中发布了的任何项目列表=True。假设有3个类别(A、B、C),每个类别有3个项目列表(A1、A2、A3、B1、B2、B3、C1、C2、C3)。并且让所有人都有是发布的=False,除了C3


现在查询结果是这样的。它只返回包含所有列表项C1、C2、C3的C类别。这不是期望的结果。我应该只得到C3,因为这是唯一发布的项目

我认为您需要在返回类别本身之前过滤这些项目

  • 筛选所有已发布的项目
  • 按已发布项目筛选所有类别
  • 也许您可以使用此方法,但之前我建议您使用
    QuerySet
    管理器

    1<代码>型号.py

    class ItemCategory(models.Model):
        category_name = models.CharField(max_length=50, unique=True)
        category_image = models.ImageField(upload_to='item-category', null=True)
    
        def get_published_items(self):
            """
            return all items contains with this single Category.
            """
            return Item.objects.published().filter(category_name__pk=self.pk)
    
        def __str__(self):
            return 'category: ' + self.category_name
    
    
    class ItemQuerySet(models.QuerySet):
    
        def published(self):
            return self.filter(is_published=True)
    
        def unpublished(self):
            return self.filter(is_published=False)
    
    
    class Item(models.Model):
        ....
        category_name = models.ForeignKey(
          ItemCategory, on_delete=models.CASCADE, 
          null=True, related_name='items')
        is_published = models.BooleanField(default=False)
    
        objects = ItemQuerySet.as_manager()
    
        def __str__(self):
            return 'item: ' + self.item_name
    
    2。views.py

    class ItemCategoryView(viewsets.ViewSet):
        permission_classes = (AllowAny,)
        serializer_class = ItemCategoryListSerializer
    
        def list(self, request, format=None):
            # find all categories first
            published_categories_by_items = [ c.category_name for c in Item.objects.published() ]
            # then, filter the categories itself.
            queryset = ItemCategory.objects.filter(pk__in=[ c.pk for c in published_categories_by_items]).distinct()
    
            serializer = ItemCategorySerializer(queryset, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
    

    您可以通过
    过滤器
    预取相关
    来实现这一点:

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

    尝试以下操作:
    queryset=itemcegory.objects.filter(items\uu is\u published=True)
    this return itemcegory with published items.no它没有。我试过了。。有任何错误或它可以工作但不返回你想要的吗?嘿@nevervoner它可以工作。谢谢你,非常欢迎!我把它贴出来作为答复。