django 如何在嵌套序列化程序中筛选来自另一个模型的字段

gfttwv5a  于 2023-03-04  发布在  Go
关注(0)|答案(1)|浏览(170)

我有以下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请求www.example.com在视图集中的get_queryset()中获得它。127.0.0.1/?price=500.
类似的问题在stackoverflow上被问了很多次,但遗憾的是,没有一个问题没有为我解决。
我看到的一个解决方案是将此函数添加到我的Product模型中,并从序列化器中调用它:

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,我可以使用它来过滤商店商品的价格,并获得产品,但是我的目标是使用Product视图集,和Product. objects. bla(). bla(). bla()...然后在这里进行过滤。
有什么想法吗?

cqoc49vn

cqoc49vn1#

你可以在序列化器中使用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})

相关问题