我有两个模型ItemCategory和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 = ItemCategory.objects.filter(items__in = Item.objects.filter(is_published = True))queryset = ItemCategory.objects.filter(items__is_published = True)
我认为这个查询都有效,但不是我想要的方式。下面是它如何运作。
返回ItemCategory列表,其中 is_published = True的项目列表。说有3个类别(A,B,C),每个类别有3个项目列表(A1,A2,A3,B1,B2,B3,C1,C2,C3)。除C3外,让所有人都 is_published = False。
所以现在查询结果是这样的。它仅返回C类别,包含所有列表项C1,C2,C3。这不是理想的结果。我应该只获得C3,因为这是唯一发布的项目。
答案 0 :(得分:1)
您可以使用filter
和prefetch_related
:
queryset = ItemCategory.objects.filter(items__is_published=True).prefetch_related(Prefetch("items", queryset=Item.objects.fiter(is_published=True))
答案 1 :(得分:0)
我认为你需要在返回类别本身之前过滤它们。
也许您可以使用此方法,但之前我建议您使用QuerySet
经理。
<强> 1。 models.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)