【问题标题】:django REST framework - limited queryset for nested ModelSerializer?django REST framework - 嵌套 ModelSerializer 的有限查询集?
【发布时间】:2014-10-08 09:30:42
【问题描述】:

我有一个ModelSerializer,但默认情况下它会序列化我模型中的所有对象。我想将此查询集限制为仅最近的 500 个(而不是全部 5000 万个)。我该怎么做?

我目前拥有的如下:

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel

我认为我不能只在我的视图集中指定查询集的原因是这实际上是另一个序列化程序的嵌套部分。

models.py

​​>
class Container(models.Model):
    size  = models.CharField(max_length=20)
    shape = models.CharField(max_length=20)

class Item(models.Model):
    container = models.ForeignKey(Container, related_name='items')
    name  = models.CharField(max_length=20)
    color = models.CharField(max_length=20)

views.py

​​>
class ContainerViewSet(viewsets.ModelViewSet):
    queryset = Container.objects.all()  # only a handful of containers
    serializer_class = ContainerSerializer

serializers.py

​​>
class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ('name', 'color')

class ContainerSerializer(serializers.ModelSerializer):
    items = ItemSerializer(many=True)  # millions of items per container
    class Meta:
        model = Container
        fields = ('size', 'shape', 'items')

【问题讨论】:

    标签: django serialization django-rest-framework


    【解决方案1】:

    你可以使用source参数

    class Container(models.Model):
        ...
        def get_items(self):
            return self.items[:500]
    

    在序列化器中

    items = ItemSerializer(many=True, source='get_items', )
    

    【讨论】:

    • 我认为这个答案比@Johndt6 的答案更明确,哪种方法有点像视图。这是另一种序列化器样式,返回对象 as many=true。
    【解决方案2】:

    在您的视图集中,您可以按如下方式指定查询集:

    from rest_framework import serializers, viewsets
    
    class MyModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = MyModel
    
    class MyModelViewSet(viewsets.ModelViewSet):
        queryset = MyModel.objects.all()[:500]
        serializer_class = MyModelSerializer
    

    我认为您正在寻找的是SerializerMethodField

    所以您的代码如下所示:

    class ContainerSerializer(serializers.ModelSerializer):
        items = SerializerMethodField('get_items')
    
        class Meta:
            model = Container
            fields = ('size', 'shape', 'items')
    
        def get_items(self, container):
            items = Item.objects.filter(container=container)[:500]  # Whatever your query may be
            serializer = ItemSerializer(instance=items, many=True)
            return serializer.data
    

    一个问题是SerializerMethodField 是只读的。

    【讨论】:

    • 谢谢——我已经编辑了我的问题以更彻底地解释我的情况。
    • 只是一个细节。您不需要在 SerializerMethodField(...) 上指定“get_items”,因为它是使用始终“get_”+ 属性名称自动推断出来的
    • @xleon 很高兴知道这一点。但除非我们非常熟悉,否则我们可能仍然更喜欢直言不讳..
    • @Yeo 在最新的 Django Rest Framework 版本中,在 ModelSerializer 类的 SerializerMethodField(...) 中指定“get_”+属性名称将引发 AssertionError,因为它被认为是多余的。因此,如果您使用的是 ModelSerializer,请不要将函数名称传递给 SerializerMethodField(...)。
    • 如果ItemSerializer 包含需要上下文的字段,例如HyperlinkedIdentityField,您可以将context=self.context 作为第三个参数传递给ItemSerializer 实例化。
    猜你喜欢
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    • 2014-09-21
    • 2021-03-17
    相关资源
    最近更新 更多