【问题标题】:django rest framework how to add entries for multiple tables with one request?django rest框架如何通过一个请求为多个表添加条目?
【发布时间】:2018-02-18 20:13:13
【问题描述】:

我试图在向电影模型添加电影的同时向流派模型添加流派,但是在尝试添加尚不存在的流派条目时我得到以下响应对象(工作正常如果它已经存在于表中):

{'genres': ['Object with genre=Mystery does not exist.']}

我认为它应该使用 MovieSerializer 的 create() 方法中的 object.get_or_create() 工作,但它似乎不起作用。

我还通过 POST 请求以以下格式发送数据:

{'tmdb_id': 14,
'title': 'some movie',
'release_date': '2011-12-12',
'genres': ['Action', 'Mystery']}

不确定这是否重要。

代码如下:

Views.py

class CreateMovieView(generics.ListCreateAPIView):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer

    def perform_create(self, serializer):
        """Save the post data when creating a new movie."""
        serializer.save()


class MovieDetailsView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer

Models.py

class Genre(models.Model):

    genre = models.CharField(max_length=65)

    def __str__(self):
        return "{}".format(self.genre)


class Movie(models.Model):

    tmdb_id = models.IntegerField(primary_key=True)
    title = models.CharField(max_length=255)
    release_date = models.DateField()
    imdb_id = models.CharField(max_length=255, blank=True)
    img_path = models.CharField(max_length=255, blank=True)
    runtime = models.CharField(max_length=65, blank=True)
    synopsis = models.TextField(blank=True)
    imdb_rating = models.DecimalField(max_digits=3, decimal_places=1, blank=True, null=True)
    metascore = models.IntegerField(blank=True, null=True)

    genres = models.ManyToManyField(Genre, related_name='genres', blank=True)

    def __str__(self):
        return "{}".format(self.title)

serializers.py

class MovieSerializer(serializers.ModelSerializer):
    """Serializer to map the Model instance into JSON format."""

    genres = serializers.SlugRelatedField(slug_field='genre', many=True, queryset=Genre.objects.all())

    class Meta:
        """Meta class to map serializer's fields with the model fields."""
        model = Movie
        fields = ('tmdb_id',
                  'imdb_id',
                  'title',
                  'release_date',
                  'img_path',
                  'runtime',
                  'synopsis',
                  'imdb_rating',
                  'metascore',
                  'genres')

def create(self, validated_data):
    genres_data = validated_data.pop('genres')
    movie = Movie.objects.create(**validated_data)

    for genre_name in genres_data:
        genre, created = Genre.objects.get_or_create(genre=genre_name)
        movie.genres.add(genre)

    return movie

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    我不知道为什么这是你得到的错误,但似乎你没有正确使用视图来允许创建电影实例。 ListCreateAPIView 可让您创建电影列表 相反,您应该将 CreateModelMixin 添加到您的其他视图中:

    class MovieDetailsView(generics.RetrieveUpdateDestroyAPIView,
                           mixins.CreateModelMixin):
        queryset = Movie.objects.all()
        serializer_class = MovieSerializer
    

    或者,更好的是,使用 ModelViewSet:

    from restframework import viewsets
    
    class MovieViewSet(viewsets.ModelViewSet):
        queryset = ...
    

    【讨论】:

    • 我现在已经实现了 ModelViewSet,但是我仍然得到相同的响应。我现在认为问题在于数据没有被正确序列化。我尝试对其进行测试,但似乎 MovieSerializer 没有正确序列化类型的嵌套对象。尝试序列化时出现错误'str' object has no attribute 'genre'
    • 可能会覆盖 ModelSerializer.to_internal_data() 方法来获取或创建流派并将新流派 ID 放入数据中。确保您确切了解 SlugRelatedField 的功能。
    猜你喜欢
    • 2018-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    • 2015-06-18
    相关资源
    最近更新 更多