[英]Rest framework: different serializer for input and output data on post/put operations
可以说我有以下模型:
class Download(MPTTTimeStampedModel):
endpoint = models.ForeignKey(EndPoint, related_name="downloads",)
class EndPoint(TimeStampedModel):
name = models.CharField(max_length=100, verbose_name=_(u"Nombre"))
url = models.CharField(max_length=2000, verbose_name=_(u"Url"))
这些序列化器:
class DownloadSerializer(serializers.ModelSerializer):
class Meta:
model = Download
fields = ('id', 'endpoint')
def create(self, validated_data):
...
def update(self, validated_data):
...
class EndPointSerializer(serializers.ModelSerializer):
class Meta:
model = EndPoint
fields = ('id', 'name', 'url')
def create(self, validated_data):
...
def update(self, validated_data):
...
这个通用的api视图:
class DownloadList(generics.ListCreateAPIView):
queryset = Download.objects.all()
serializer_class = DownloadSerializer
这将允许我通过发送如下所示的json表示来创建下载:
{
'id': null,
'endpoint': 19
}
创建后,Web服务将向我发回具有数据库ID的数据。 现在,我实际上希望Web服务不仅向我发送回端点ID,而且还向我发送对象的完整表示,如下所示:
{
'id': null,
'endpoint': {
'id': 19,
'name': 'my endpoint',
'url': 'http://www.my-endpoint.com/'
}
}
我可以使用以下序列化器来管理:
class DownloadDetailedSerializer(DownloadSerializer):
endpoint = EndPointSerializer(many = False, read_only=False)
现在是实际的问题:我如何告诉我的通用视图将最后一个序列化器用于返回的数据,同时保留原始DownloadSerializer用于输入?
编辑 :@neverwalkeralone建议的方法是创建自定义字段并覆盖to_representation方法。 但这导致我在serializer = EndPointSerializer(value)行中出现异常,经过一些测试,我发现最好从RelatedField继承我的自定义字段。 这意味着也要覆盖to_internal_value。 因此,这终于完成了工作:
class EndPointField(serializers.RelatedField):
def to_representation(self, value):
serializer = EndPointSerializer(value)
return serializer.data
def to_internal_value(self, instance):
endpoint = EndPoint.objects.get(pk=instance)
return endpoint
def get_queryset(self):
return EndPoint.objects.all()
您可以定义自定义字段,使用to_representation
方法来自定义输出格式:
class EndPointField(serializers.PrimaryKeyRelatedField):
def to_representation(self, value):
serializer = EndPointSerializer(value)
return serializer.data
def get_queryset(self):
return models.EndPoint.objects.all()
并在DownloadSerializer
中将其用于端点字段:
class DownloadSerializer(serializers.ModelSerializer):
endpoint = EndPointField()
class Meta:
model = Download
fields = ('id', 'endpoint')
UPD
基于Kilian Perdomo Curbelo的反馈, EndPointField
的to_representation
值应替换为端点实例:
def to_representation(self, value):
endpoint = EndPoint.objects.get(pk=value.pk)
serializer = EndPointSerializer(endpoint)
return serializer.data
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.