通过防止完全响应序列化来优化DRF请求后处理

时间:2018-10-27 21:46:05

标签: python django rest optimization django-rest-framework

我为AViewSet定义了ASerializerAModel

class AModel(Model):
    name = CharField(16)
    text = TextField()
    related = ForeignField('ARelated')

class AViewSet(ModelViewSet):
    queryset = AModel.objects.all()
    serializer_class = ASerializer

class ASerializer(Serializer):
    class Meta(object):
        model = AModel
        fields = '__all__'

我写了一个RESTful客户端,它在多个请求中向该视图/端点发布了很多数据,创建了许多AModel记录。我注意到,但是,服务器时间的大部分时间都花在了生成响应上,在进行了一段时间的搜索之后,我发现了对nested relationship hazard的一些引用,这似乎是一个不错的解决方法,但让我想知道:

我已经知道我发布的内容,并且不需要pk,所以我可以防止序列化响应完全发生吗?我可以代替序列化插入的行数吗?

看看DRF的CreateModelMixin类:

class CreateModelMixin(object):
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

我意识到我可以重写create方法并重新实现它,而无需返回serializer.data作为响应的一部分,因此它看起来类似于:

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response({}, status=status.HTTP_201_CREATED, headers=headers)

关于这种方法,我有两个问题:

  1. 这种防止使用POST创建的对象完全序列化的做法是否对RESTful设计模式,方法,意识形态等有意义?
  2. 这是否真的避免select存取所有相关数据(以及执行任何SerializerMethodField等)?

1 个答案:

答案 0 :(得分:1)

在这里采用基本的 ModelViewset ModelSerializer 组合:)就像

# serializers.py
class SampleSerializer(serializers.ModelSerializer):
    class Meta:
        model = SampleModel
        fields = '__all__'

# views.py
class SampleViewset(viewsets.ModelViewSet):
    queryset = SampleModel.objects.all()
    serializer_class = SampleSerializer

为什么DRF将所有数据返回给客户端?
在这里, SampleViewset 每次都使用 SampleSerializer ,它将序列化 all 字段在序列化程序类中定义。按照当前配置

可能的解决方案是什么?
为此可能的解决方案是通过某种方式停止某些字段的序列化过程:)

怎么办?
据我所知,这可以通过两种方式完成。
1.对SampleSerializer方法使用最小的POST
2.对to_representation()请求覆盖SampleSerializer POST 方法

方法1:使用其他序列化器
定义一个新的序列化程序类,其中包含您希望在POST请求

时发送并检索的字段
class SampleSerializerMinimal(serializers.ModelSerializer):
    class Meta:
        model = SampleModel
        fields = ('id', 'name', 'age')

现在,我们要告诉视图集将此序列化程序用于POST方法,可以在视图集的 get_serializer_class() 中完成

class SampleViewset(viewsets.ModelViewSet):
    queryset = SampleModel.objects.all()
    serializer_class = SampleSerializer

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return SampleSerializerMinimal
        return SampleSerializer



方法2:覆盖to_representation()方法

class SampleSerializer(serializers.ModelSerializer):
    class Meta:
        model = SampleModel
        fields = '__all__'

    def to_representation(self, instance):
        try:
            if self.context['view'].request.method == 'POST':
                return {
                    "id": instance.id,
                    "name": instance.name,
                    "age": instance.age
                }
        except KeyError:
            return super(SampleSerializer, self).to_representation(instance)
        return super(SampleSerializer, self).to_representation(instance)



什么是最好的方法?
我觉得 Method-1 是DRF的处理方式,但是您不能仅将id添加到fields,因为POST请求可能需要更多字段。
Method-2 也不错,但是如果您要返回n字段并将其写入{{1 }} 方法


UPDATE-1
方法3:to_representation()method-1的组合

method-2



UPDATE-2

  

这种防止使用POST创建的对象进行完全序列化的做法是否对RESTful设计模式,方法,意识形态等有意义?

# serializer.py class SampleSerializerMinimal(serializers.ModelSerializer): class Meta: model = SampleModel fields = ('id', 'name', 'age') def to_representation(self, instance): """ we don't have to check the request method, because DRF routing only POSt requests to this serializer """ return {"id": instance.id} # views.py class SampleViewset(viewsets.ModelViewSet): queryset = SampleModel.objects.all() serializer_class = SampleSerializer def get_serializer_class(self): if self.action.method == 'POST': return SampleSerializerMinimal return SampleSerializer 正在调用 .data 方法,该方法调用与 相关的对象以及序列化程序中的所有其他字段 。 (Source code of data property of serializer)因此,如果您可以避免该 to_representation() 调用,那就太好了!。
由于在POST请求后,我已经看到许多具有单个细节的API响应,例如 .data ,所以我认为您的 不会过度使用DRF模式和其他功能< / em>

  

这实际上会避免选择所有相关数据(以及执行任何SerializerMethodFields等)吗?

是的。如上所述,除非调用 {"status":true}

,否则它将不会调用序列化过程