我为AViewSet
定义了ASerializer
和AModel
:
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)
关于这种方法,我有两个问题:
select
存取所有相关数据(以及执行任何SerializerMethodField
等)?答案 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}