Django Rest Framework 多对多序列化器问题

问题描述 投票:0回答:1

我正在 Django Rest Framework 中创建 API,但在多对多关系方面遇到问题。

我正在尝试创建一部电影并为其分配类型(电影和类型之间的多对多关系)。

这是我的模型:

class Genre(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(null=False,blank=False,max_length=50)
    
    def __str__(self):
        return self.name

class Movie(models.Model):
    id = models.IntegerField(primary_key=True,null=False,blank=False)
    adult = models.BooleanField(null=False,blank=False)
    backdrop_path = models.CharField(null=True,blank=True,max_length=200)
    budget = models.BigIntegerField (default=0)
    homepage = models.CharField(null=True,blank=True,max_length=200)
    original_language = models.CharField(max_length=10)
    original_title = models.CharField(max_length=200)
    overview = models.CharField(max_length=1000)
    poster_path = models.CharField(null=True,blank=True,max_length=200)
    release_date = models.DateField(null=True,blank=True,)
    revenue = models.BigIntegerField (default=0)
    runtime = models.IntegerField(null=True,blank=True)
    status = models.CharField(max_length=50)
    tagline = models.CharField(null=True,blank=True,max_length=100)
    title = models.CharField(max_length=200)
    genres = models.ManyToManyField(Genre,blank=True)
    
    def __str__(self):
        return self.title

这是我的序列化器:

class GenresSerializers(serializers.ModelSerializer):
    class Meta:
        model = Genre
        fields = ['id','name']
        
    def create(self,validated_data):
        
        instance, _ = Genre.objects.get_or_create(**validated_data)
        return instance
    
class MovieGenreSerializer(serializers.ModelSerializer):
    class Meta:
        model = Genre
        fields = ['id']
        
    def create(self, validated_data):
        instance, _ = Genre.objects.get(**validated_data)
        return instance
    
class MoviesSerializer(serializers.ModelSerializer):
    genres = GenresSerializers(many= True)
    
    class Meta:
        model = Movie
        fields = [ 'id', 'adult', 'backdrop_path', 'budget', 'homepage', 'original_language', 'original_title', 'overview', 'poster_path', 'release_date', 'revenue', 'runtime', 'status', 'tagline', 'title', 'genres'
            ]
        # extra_kwargs = {'id': {'read_only': True}}
        
        
    def create(self, validated_data):
        genres_data = validated_data.pop('genres', []) 
        
        genresInstances = []
        for genre in genres_data:
            genresInstances.append(Genre.objects.get(pk = genre['id']))
        movie = Movie.objects.create(**validated_data)
        movie.genre.set(genresInstances)
        return movie

和我的观点:

class MovieViewSet(viewsets.ModelViewSet):
    queryset = Movie.objects.all()
    serializer_class = MoviesSerializer

当我尝试使用此请求正文创建一部新电影时(我已经创建了类型):

{
  "id": 425,
  "adult": false,
  "backdrop_path": "/kK5OeulwVDniPgjNOGHvzcORzdG.jpg",
  "budget": 59000000,
  "homepage": "http://www.iceagemovies.com/films/ice-age",
  "original_language": "en",
  "original_title": "Ice Age",
  "overview": "With the impending ice age almost upon them, a mismatched trio of prehistoric critters – Manny the woolly mammoth, Diego the saber-toothed tiger and Sid the giant sloth – find an orphaned infant and decide to return it to its human parents. Along the way, the unlikely allies become friends but, when enemies attack, their quest takes on far nobler aims.",
  "poster_path": "/stQoHvo0q6ZcEkji2Z1wlAxKnDq.jpg",
  "release_date": "2002-03-10",
  "revenue": 383257136,
  "runtime": 81,
  "status": "Released",
  "tagline": "They came. They thawed. They conquered.",
  "title": "Ice Age",
  "genres": [
    {
      "id": 16
    },
    {
      "id": 35
    },
    {
      "id": 10751
    },
    {
      "id": 12
    }

  ]
}

它像这样返回:

{
  "genres": [
    {
      "id": [
        "genre with this id already exists."
      ]
    },
    {
      "id": [
        "genre with this id already exists."
      ]
    },
    {
      "id": [
        "genre with this id already exists."
      ]
    },
    {
      "id": [
        "genre with this id already exists."
      ]
    }
  ]
}
python django django-rest-framework
1个回答
0
投票

不要使用子序列化器,例如使用

SlugRelatedFieldSerializer
 [drf-doc]:

class MoviesSerializer(serializers.ModelSerializer):
    genres = serializers.SlugRelatedField(
        many=True, queryset=Genre.objects.all(), slug_field='name'
    )

    class Meta:
        model = Movie
        fields = [
            'id',
            'adult',
            'backdrop_path',
            'budget',
            'homepage',
            'original_language',
            'original_title',
            'overview',
            'poster_path',
            'release_date',
            'revenue',
            'runtime',
            'status',
            'tagline',
            'title',
            'genres',
        ]
        # extra_kwargs = {'id': {'read_only': True}}

    # no create

您可以使用以下命令创建项目:

{
    # …,
    "genres": ["horror", "music", "musical"]
}
© www.soinside.com 2019 - 2024. All rights reserved.