繁体   English   中英

REST框架:不同的序列化器,用于后期处理的输入和输出数据

[英]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的反馈, EndPointFieldto_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM