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



我已经为我的AModel:定义了AViewSetASerializer

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记录。然而,我注意到,服务器的大部分时间都花在了生成响应上,在谷歌上搜索了一段时间后,我发现了一些关于嵌套关系风险的引用,这似乎是一个不错的解决方案,但让我想知道:

我已经知道我发布了什么,而且我不需要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等(

让我们在这里取基本的ModelViewsetModelSerializer组合:(

# 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,它将串行化序列化程序类中定义的所有字段。根据当前配置

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

怎么办
据我所知,这可以通过两种方式来实现
1.对POST方法使用最小的SampleSerializer
2。在POST请求上覆盖SampleSerializerto_representation()方法

方法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)



什么是最好的方法
我觉得方法1更像是DRF的做事方式,但不能只将id添加到fields中,因为POST请求可能需要更多字段
Method-2to也很好,但如果您想返回n字段并将其写入to_representation()方法,它就不太干净了


更新-1
方法-3:method-1method-2的组合

# serializer.py
classSampleSerializerMinimal(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



更新-2

这种阻止用POST创建的对象完全序列化的做法对RESTful设计模式、方法、意识形态等有意义吗?

.data正在调用to_representation()方法,该方法调用相关对象和序列化程序中的所有其他字段。(序列化程序的data属性的源代码(因此,如果您可以避免.data调用,那就太好了
由于我在POST请求后看到了许多API响应,其中只有一个细节,如{"status":true},我不认为您的方法过度扼杀了DRF模式和其他东西

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

是。如上所述,它不会调用序列化进程,除非调用.data

最新更新