Python Rest框架:post/put操作中输入和输出数据的不同序列化程序

Python Rest框架:post/put操作中输入和输出数据的不同序列化程序,python,django,rest,web-services,django-rest-framework,Python,Django,Rest,Web Services,Django Rest Framework,假设我有这些模型: 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

假设我有这些模型:

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
}
{
    'id': null,
    'endpoint': {
        'id': 19,
        'name': 'my endpoint',
        'url': 'http://www.my-endpoint.com/'
    }
}
创建后,web服务将从数据库中返回id为的数据。现在,我实际上希望web服务不仅返回端点id,还返回对象的完整表示形式,如下所示:

{
    'id': null,
    'endpoint': 19
}
{
    'id': null,
    'endpoint': {
        'id': 19,
        'name': 'my endpoint',
        'url': 'http://www.my-endpoint.com/'
    }
}
我会用这个序列化程序来管理它:

class DownloadDetailedSerializer(DownloadSerializer): 
    endpoint = EndPointSerializer(many = False, read_only=False)
现在实际的问题是:如何告诉我的泛型视图对返回的数据使用最后一个序列化程序,同时保留原始的下载序列化程序作为输入

编辑:正如@neverwalkeralone建议的那样,方法是创建一个自定义字段并覆盖到_表示方法。但这导致了serializer=EndPointSerializer(value)行中的一个异常,经过一些测试,我发现从RelatedField继承我的自定义字段会更好。这也意味着覆盖到内部值。以下是最终完成工作的原因:

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到_表示的值应替换为endpoint实例:

def to_representation(self, value):
    endpoint = EndPoint.objects.get(pk=value.pk)
    serializer = EndPointSerializer(endpoint)
    return serializer.data

也许我做错了什么,但尝试了这个,仍然有同样的问题。我的输入和输出数据使用相同的序列化,在本例中为EndPointField。我的意思是,我需要我的web服务以一种格式接受输入(只是相关端点的主键),并以另一种格式返回创建的对象(包含数据库中完整信息的字典)@KilianPerdomoCurbelo yes,使用此方法,您将只发布端点id。对于只读请求,端点字段将返回详细的端点信息。你能展示一下你试过的吗?和输入/输出数据?您需要在视图中使用
下载序列化程序
序列化程序。和
EndPointField
应该是此序列化程序中的唯一字段。不要说原始代码不起作用,原因是EndPointField继承自PrimaryKeyRelatedField。这导致我在serializer=EndPointSerializer(value)行中出现异常,不确定原因,但我认为是因为“value”不是EndPointSerializer所期望的类型。长话短说,经过一些不同结果的更改后,我终于找到了正确的代码。你的提示是对的,所以我认为你的解决方案是有效的。我正在更新我评论中的代码。@KilianPerdomoCurbelo感谢您的反馈。我也更新了我的答案,现在应该可以了。