簡體   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