如何在不使用嵌套序列化器创建模型的情况下通过Serializer创建模型实例?

Iva*_*kin 7 django django-rest-framework

我的模型有很多链接:

class Travel(BaseAbstractModel):

    tags = models.ManyToManyField(
        Tag,
        related_name='travels',
        )
    owner = models.ForeignKey(
        'users.TravelUser',
        related_name='travel_owner'
        )
    payment = models.ForeignKey(
        Payment,
        related_name='travels',
        )
    country = models.ForeignKey(
        Country,
        related_name='travels,
        )
    ........
Run Code Online (Sandbox Code Playgroud)

其中许多模型只有两个具有唯一名称和图像的字段.我为每个模型创建了序列化器并将它们放入TravelSerializer

class TravelBaseSerializer(DynamicFieldsModelSerializer):

    owner = UserSerializer(required=False)
    tags = TagSerializer(many=True)
    payment = PaymentSerializer()
    country = CountrySerializer()  
Run Code Online (Sandbox Code Playgroud)

根据我覆盖的文档create()update.
问题是,当我发送JSON数据时,Django从嵌套的序列化器创建每个模型.但我想只创建Travel实例.此外,我希望不仅接收和响应序列化对象pk字段.

更新
我解决了这个问题,把代码放在答案中.现在我可以接收并响应Serializer数据而无需创建对象.但我认为DRF提供了更优雅的方法.这是我与DRF的第一个项目,也许我想念一些东西,这是一个更简单的解决方案.

Iva*_*kin 2

我决定覆盖to_internal_value()将其放入自定义序列化器中并从中继承所有嵌套序列化器:

class NestedRelatedSerializer(serializers.ModelSerializer):

    def to_internal_value(self, data):
        try:
           pk = data['pk']
        except (TypeError, KeyError):
        # parse pk from request JSON
            raise serializers.ValidationError({'_error': 'object must provide pk!'})
        return pk
Run Code Online (Sandbox Code Playgroud)

pk从中获取所有内容并保存在createupdated方法中:

    def update(self, instance, validated_data):
        # If don't get instance from db, m2m field won't update immediately
        # I don't understand why
        instance = Travel.objects.get(pk=instance.pk)
        instance.payment_id = validated_data.get('payment', instance.payment_id)
        instance.country_id = validated_data.get('country', instance.country_id)
        # update m2m links
        instance.tags.clear()
        instance.tags.add(*validated_data.get('tags'))
        instance.save()
        return instance
Run Code Online (Sandbox Code Playgroud)