简体   繁体   中英

django rest framework how to add entries for multiple tables with one request?

I'm trying to add genres to the Genre model at the same time as adding a Movie to the movie model, however I get the following response object when trying to add a Genre entry that doesn't already exist (works fine if it exists in the table already):

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

I thought it should work using the object.get_or_create() in the create() method of the MovieSerializer but it doesn't seem to work.

Also I'm sending data by POST request in the format:

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

not sure if that matters.

Here's the code:

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

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)

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

I'm not sure why this is the error you get, but seems like your'e not using the Views correctly to allow creation of Movie instances. the ListCreateAPIView lets you create lists of movies you should, instead, add a CreateModelMixin to your other view:

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

or, even better, use the ModelViewSet:

from restframework import viewsets

class MovieViewSet(viewsets.ModelViewSet):
    queryset = ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM