Django Rest框架在不存在外键时使用序列化程序创建新记录

时间:2020-04-28 22:56:36

标签: django-rest-framework

说我有这两种模型:

class App(models.Model):
 label = models.CharField(max_length=32)

class Endpoint(models.Model):
 main_app = models.ForeignKeyField(App, on_delete=models.CASCADE)
 ...

class EndpointSerializer(serializers.HyperlinkedModelSerializer):
 main_app = serializers.SlugRelatedField(queryset=App.objects.all(), slug_field='label')

  class Meta:
   model = ReviewComponent
   fields = [
    'id', 
    'main_app'
        ]

当我想用现有的应用程序创建一个新的端点时,这很简单:

serializer = EndpointSerializer(data={'main_app': 'foo'...})
serializer.is_valid()
serializer.save()

但是当我要使用不存在的应用程序创建新端点时,这种方法不起作用,那么正确的方法是什么?

我总是可以为App添加一个序列化程序,通过AppSerializer创建App,然后在EndpointSerializer上恢复创建,但是我不认为这是正确的方法。

1 个答案:

答案 0 :(得分:0)

此处的Django rest框架文档中有一个示例:https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers

在App模型中使用序列化程序似乎是在Django rest框架中管理App对象创建的相当普遍的方法。将其调整为您问题中的模型可能类似于:

from django.db import models
from rest_framework import serializers


class App(models.Model):
    label = models.CharField(max_length=32)


class Endpoint(models.Model):
    main_app = models.ForeignKey(App, on_delete=models.CASCADE)


class AppSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = App
        fields = '__all__'


class EndpointSerializer(serializers.HyperlinkedModelSerializer):
    main_app = AppSerializer()

    class Meta:
        model = Endpoint
        fields = '__all__'

    def create(self, validated_data):
        main_app_data = validated_data.pop('main_app')
        main_app = App.objects.get_or_create(**main_app_data)
        validated_data['main_app'] = main_app
        return super().create(validated_data)
----------------------------------------------------
>>> from qqq.models import App, Endpoint, AppSerializer, EndpointSerializer
>>> serializer = EndpointSerializer(data={'main_app': {'label': 'label-1'}})   # notice the nested dict here
>>> serializer.is_valid()
True
>>> serializer.save()
<Endpoint: Endpoint object (1)>
>>> App.objects.all()
<QuerySet [<App: App object (1)>]>
>>> Endpoint.objects.all()
<QuerySet [<Endpoint: Endpoint object (1)>]>

您提到您不想创建AppSerializer,但是如果没有它,您会遇到两个我可以想到的问题。

  1. EndpointSerializer(data={'main_app'...行中创建Endpoint和App实例时,django rest将始终尝试在App表中查找App对象,却永远找不到它,从而引发错误。
  2. 默认情况下,所有Django Rest的<Thing>RelatedField都是只读的。因此,要写入嵌套数据,您需要通过覆盖.create()和/或.update()方法来手动进行。 enter image description here