Как добавить существующие объекты в поле ManyToMany с помощью Serializer? - PullRequest
0 голосов
/ 06 февраля 2020

Я пытаюсь создать API с Artists and Songs, с отношениями ManyToMany между ними. Использование API для создания композиции с исполнителем, которого нет в базе данных, работает нормально. Проблема возникает, когда я пытаюсь использовать метод POST для создания новой песни с исполнителем, который уже существует в базе данных. Я попытался переписать метод SongSerializer create(), используя get_or_create(), основываясь на другом посте здесь, но я продолжал получать ошибки Bad Request, когда Artist уже существует в базе данных. Соответствующие фрагменты кода:

models.py

class Artist(models.Model):
    artist_name = models.CharField(max_length=200, unique=True)

    class Meta:
        ordering = ['artist_name']

    def __str__(self):
        return self.artist_name

class Song(models.Model):
    song_title = models.CharField(max_length=200)
    artists = models.ManyToManyField(Artist, related_name='songs')

    class Meta:
        ordering = ['song_title']

    def __str__(self):
        return self.song_title

serializers.py

class ArtistNameSerializer(serializers.ModelSerializer):
    class Meta:
        model = Artist
        fields = ('artist_name',)

    def to_representation(self, value):
        return value.artist_name

class SongTitleSerializer(serializers.ModelSerializer):
    songs = serializers.PrimaryKeyRelatedField(read_only=True, many=True)

    def to_representation(self, value):
        return value.song_title

    class Meta:
        model = Song
        fields = ('songs',)

class ArtistSerializer(serializers.HyperlinkedModelSerializer):
    songs = SongTitleSerializer(read_only=True, many=True)

    class Meta:
        model = Artist
        fields = ('id', 'artist_name', 'songs')

class SongSerializer(serializers.HyperlinkedModelSerializer):
    artists = ArtistNameSerializer(many=True)

    class Meta:
        model = Song
        fields = ('id', 'song_title', 'artists',)

    def create(self, validated_data):
        artist_data = validated_data.pop('artists')
        song = Song.objects.create(**validated_data)
        song.save()
        for artist_item in artist_data:
            a, created = Artist.objects.get_or_create(artist_name=artist_item['artist_name'])
            song.artists.add(a)
        return song

Я провел несколько тестов и похоже, что программа не даже go в метод create(), который я использую, и сразу же показываю мне ошибку Bad Request. Что мне не хватает? Заранее спасибо!

1 Ответ

0 голосов
/ 06 февраля 2020

На вашей модели Artist у вас есть ограничение на поле artist_model (unique = True)

, если вы печатаете соответствующий сериализатор с:

print(SongSerializer())

, вы получаете что-то вроде этого:

SongSerializer():
id = IntegerField(label='ID', read_only=True)
song_title = CharField(max_length=200)
artists = ArtistNameSerializer(many=True):
artist_name = CharField(max_length=200, validators=[<UniqueValidator(queryset=Artist.objects.all())>])

под полем Artist_Name является Validator «UniqueValidator»

, поэтому в случае операции записи вы можете отключить валидатор в сериализаторе с помощью:

class ArtistNameSerializer(serializers.ModelSerializer):
class Meta:
    model = models.Artist
    fields = ('artist_name',)
    extra_kwargs = {
        'artist_name': {
            'validators': [],
        }
    }

надеюсь, что это поможет ..

...