繁体   English   中英

Django REST框架无需创建嵌套序列化程序即可创建嵌套序列化程序

[英]Django REST Framework Saving Nested Serializers Without Creating Them

我有一个这样的序列化器:

class DataSetColumnSerializer(serializers.ModelSerializer):
    custom_target = target_serializers.CustomTargetSerializer()

    class Meta:
        model = dataset_models.DataSetColumn

custom_target使用以下序列化器:

class CustomTargetSerializer(serializers.ModelSerializer):
    class Meta:
        model = target_models.CustomTarget

我传回一个对象,该对象包含我想为该DataSetColumn设置的custom_target 当我验证序列化器并将其保存时:

serializer = serializers.DataSetColumnSerializer(column, data=request.DATA)

if serializer.is_valid():
    serializer.save()

custom_target序列化程序将创建一个新的CustomTarget而不仅仅是将DataSetColumncustom_target设置为DataSetColumn的对象。我尝试将CustomTargetSerializer设置为只读。 从某种意义上说,它不会创建新的CustomTarget但也不会将custom_target设置为该对象,因此可以正常工作。

如何在序列化的DataSetColumn对象上使用serializer.save()custom_target设置为传入的嵌套对象,而不是从嵌套对象创建新对象?

这是一种相当“肮脏”的方法:

pre_save处理程序中,您可以将custom_target重置为仅具有ID。 像这样:

def pre_save(self, obj):
    if 'custom_target' in self.request.DATA:
        custom_target = self.request.DATA['custom_target']
        self.request.DATA['custom_target'] = custom_target['id']

现在想不出任何更好/更清洁的解决方案,但是如果我找到了,我会写:)

在我看来,从REST框架的角度来看,最有效的解决方案是分别使用嵌套的序列化程序和PrimaryKeyRelatedField 有了它,您可以将CustomTarget嵌套对象作为custom_target接收,并可以通过在创建时提供custom_target_id作为POST参数的ID来关联CustomTarget对象。

class DataSetColumnSerializer(serializers.ModelSerializer):
    custom_target = target_serializers.CustomTargetSerializer(read_only=True)
    custom_target_id = serializers.PrimaryKeyRelatedField(source='custom_target')

class Meta:
    model = dataset_models.DataSetColumn

但是,最终将获得两个属性custom_targetcustom_target_id ,这可能并不理想。 作为通用解决方案,可以实现自定义字段。

通用方法:定制相关领域

class NestedRelatedField(serializers.PrimaryKeyRelatedField):
    def __init__(self, serializer_class, *args, **kwargs):
        self.serializer = serializer_class()
        super(NestedRelatedField, self).__init__(queryset=serializer_class.Meta.model.objects.all(), *args, **kwargs)

    def to_representation(self, instance):
        return self.serializer.to_representation(instance)

用作:

class DataSetColumnSerializer(serializers.ModelSerializer):
    custom_target = NestedRelatedField(CustomTargetSerializer)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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