我已经为我的AModel
:定义了AViewSet
和ASerializer
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)
关于这种方法,我有两个问题:
- 这种阻止用POST创建的对象完全序列化的做法对RESTful设计模式、方法、意识形态等有意义吗
- 这实际上会避免
select
处理所有相关数据吗(以及执行任何SerializerMethodField
等(
让我们在这里取基本的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
,它将串行化序列化程序类中定义的所有字段。根据当前配置
可能的解决方案是什么
可能的解决方案是通过某种方式停止某些字段的序列化过程:(
怎么办
据我所知,这可以通过两种方式来实现
1.对POST
方法使用最小的SampleSerializer
类
2。在POST
请求上覆盖SampleSerializer
的to_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-2
to也很好,但如果您想返回n
字段并将其写入to_representation()
方法,它就不太干净了
更新-1
方法-3:method-1
和method-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