Django:向具有外键关系的模型添加新行

时间:2018-07-28 13:27:19

标签: django django-models

我有一个带有以下代码的django rest API:

models.py:

from django.db import models

class Actor(models.Model):
    id = models.CharField(max_length = 50, primary_key = True)
    login = models.CharField(max_length = 50, unique = True, blank = False)
    avatar_url = models.CharField(max_length = 100, blank = False)

    def __str__(self):
        return self.login

class Repo(models.Model):
    id = models.CharField(max_length = 50, primary_key=True)
    name = models.CharField(max_length =50, blank=False)
    url = models.CharField(max_length=100, blank=False, unique = True)

    def __str__(self):
        return self.name

class Event(models.Model):
    id = models.CharField(max_length = 50, primary_key = True)
    type = models.CharField(max_length = 50)
    actor = models.ForeignKey(Actor, on_delete = models.PROTECT)
    repo = models.ForeignKey(Repo, on_delete=models.CASCADE)
    created_at = models.DateField()

    def __str__(self):
        return self.name

serializers.py:

from models import Actor, Repo, Event

class ActorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Actor
        fields = ('id', 'login', 'avatar_url')

class RepoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Repo
        fields = ('id', 'name', 'url')

class EventSerializer(serializers.ModelSerializer):
    actor = ActorSerializer()
    repo = RepoSerializer()

    class Meta:
        model = Event
        fields = ('id', 'type', 'actor', 'repo', 'created_at')

views.py:

from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response

from models import Actor, Repo, Event
from serializers import ActorSerializer, RepoSerializer, EventSerializer

class EventView(ModelViewSet):
    queryset = Event.objects.all()
    serializer_class = EventSerializer

事件模型具有Actor和Repo模型的外键。因此,它具有嵌套的序列化器。无论何时发送POST请求,都会将一个事件添加到事件模型中。但是在添加事件之前,还将添加Actor和Repo行。

如果我添加另一个事件,并且具有与之前相同的Actor和Repo信息,则会收到错误消息,提示那些Actor和Repo已经存在。

如何确保如果Actor和Repo条目已经存在,则事件添加仍应成功?我希望仅当Actor和Repo不存在时才创建它们。

1 个答案:

答案 0 :(得分:0)

我将您的序列化器更改为

class ActorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Actor
        fields = ('id', 'login', 'avatar_url')
        extra_kwargs = {
            "id": {"validators": []},
            "login": {"validators": []}
        }


class RepoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Repo
        fields = ('id', 'name', 'url')
        extra_kwargs = {
            "id": {"validators": []},
            "url": {"validators": []}
        }


class EventSerializer(serializers.ModelSerializer):
    actor = ActorSerializer()
    repo = RepoSerializer()

    def create(self, validated_data):
        repo, created = Repo.objects.get_or_create(**validated_data.pop('repo'))
        actor, created = Actor.objects.get_or_create(**validated_data.pop('actor'))
        return Event.objects.create(**validated_data, repo=repo, actor=actor)

    class Meta:
        model = Event
        fields = ('id', 'type', 'actor', 'repo', 'created_at')

我做了什么?
您在模型中将某些字段定义为unique,因此在序列化程序中它已成为Validator。我通过在Metaclass中添加extra_kwargs覆盖了两个序列化器的验证

要创建Writable Nested Serializers,我们必须覆盖create()

EventSerializer方法