如何在嵌套序列化器中过滤来自另一个模型的字段

问题描述 投票:0回答:1

我有以下3个模型(第三个模型店不重要)。 有商店、产品和商品(哪个商店有哪些商品以及他们提供的价格)。

class Product(models.Model):
    name=models.CharField(max_length=100)

class Shopitem(models.Model):
    product = models.ForeignKey(Product, related_name='shopitems', on_delete=models.CASCADE)
    price=models.IntegerField()
    
    #shop field is not important to my question
    shop = models.ForeignKey(Shop, related_name='shopitems', on_delete=models.CASCADE)

在我的 ProductSerializer 中,我为 ShopItemSerialzer 做了一个嵌套的序列化程序,效果很好。

但是我怎样才能得到所有产品的列表,这些产品是按商品价格过滤的?最重要的是,价格是一个查询参数,我将通过 GET 请求 127.0.0.1/?price=500.

在视图集中的 get_queryset() 中获取它

类似的问题在 stackoverflow 上问了很多,但遗憾的是没有一个能为我解决。

我看到的一个解决方案是将这个函数添加到我的产品模型中,并从序列化程序中调用它:

class Product(models.Model):
    name=models.CharField(max_length=100)
    def some_function(self):
      return ShopItem.objects.filter(product=self, price__gt=340)

class ProductSerializer(serializers.ModelSerializer):
    shopitems=ShopItemSerializer(many=True, read_only=True,source="some_function")

这很好,但不是很好。我在价格上过滤的值 340 必须硬编码到该函数中。我如何将任何参数传递给它,我通过 self.request.query_params['price'] 得到这个 some_function?

我还看到了其他解决方案,它们覆盖了序列化程序中的 def to_representation(self, data):,但我对此感到非常困惑,不确定如何正确使用它。 其他帖子中显示的一些解决方案使用 .select_related() 或 prefetch_related,但我的产品模型不指向 ShopItem,但 ShopItem 指向 Product,我可以使用它来过滤 shopitems 价格并获取产品,但我的目标是使用 Product 视图集和 Product.objects.bla().bla().bla() ...并在这里以某种方式进行过滤。

有什么想法吗?

django django-models django-rest-framework django-views django-serializer
1个回答
0
投票

你可以在序列化器中使用

default
参数来传递你想要的查询集:

class Product(models.Model):
    name = models.CharField(max_length=100)

class ShotItemsGraterThanPrice:
    requires_context = True

    def __call__(self, serializer_field):
        return  ShopItem.objects.filter(product=serializer_field.instance, price__gt=serializer_field.context['request'].query_params['price'])

class ProductSerializer(serializers.ModelSerializer):
    shopitems = ShopItemSerializer(many=True, read_only=True, default= ShotItemsGraterThanPrice())

在视图中初始化它时不要忘记将请求传递给序列化程序:

serializer = ProductSerializer(context={'request': request}) 
© www.soinside.com 2019 - 2024. All rights reserved.