Django Serializer сохраняет объект дважды

У меня есть база данных с песнями. У каждой песни есть главный исполнитель, а все остальные исполнители перечислены в M2M как исполнители.

Я потребляю данные через API следующим образом:

def populate_song(uuid):
    full_endpoint = settings.API_HOST + settings.GET_SONG_BY_ID + uuid

    headers = {
        'x-app-id': APP_ID,
        'x-api-key': API_KEY,
    }

    r = requests.get(full_endpoint, headers=headers)
    
    # Create Python object from JSON string.
    if 'object' in r.json():

        try:
            song = r.json()['object']
            song['duplicate'] = False
            existingsong = Song.objects.filter(uuid=song['uuid']).first()

            if existingsong:
                data = SongSerializer(existingsong, data=song)
            else:
                data = SongSerializer(data=song)

            data.is_valid(raise_exception=True)
            return data.save()

        except Exception as err:
            print('Error saving the song with ID:' + uuid)
            print(Exception, err)

    if 'errors' in r.json():
        # if Song is not found or is giving an error, mark this in the DB as duplicate.
        Song.objects.filter(uuid=uuid).update(duplicate=True)
        return

Это сериализатор для песни:

class SongSerializer(serializers.ModelSerializer):
    artists = ArtistSerializer(many=True, required=False)
    mainartist = ArtistSerializer(many=True, required=False)
    
    def create(self, validated_data):
        artists_data = validated_data.pop('artists', None)
        
        # AT THIS POINT THE ERROR BREAKS THE CODE
        
        song = Song.objects.create(**validated_data)

        for artist_data in artists_data:

            artist = Artist.objects.filter(uuid=artist_data.get('uuid')).first()
            if not artist:
                artist = Artist.objects.create(**artist_data)

            if not song.mainartist:
                song.mainartist = artist # populate mainartist with the first SC artist
                continue
                song.save()
                continue

            song.artists.add(artist)

        return song

    def update(self, instance, validated_data):
        
        artists_data = validated_data.pop('artists', None)
        instance.artists.clear() # clear all M2M artists
        Song.objects.filter(pk=instance.id).update(**validated_data) # hack to update the object in one line of code.

        for artist_data in artists_data:
            artist = Artist.objects.filter(uuid=artist_data.get('uuid')).first()
            if not artist:
                artist = Artist.objects.create(**artist_data)
                instance.save()
                continue

            instance.artists.add(artist)

        return instance

Но я получаю следующую ошибку:

<class 'Exception'> duplicate key value violates unique constraint "core_song_pkey"
DETAIL:  Key (id)=(533588) already exists.

Похоже, что код уже сохранен перед <>, но я не могу понять, почему. Я проверил в БД и объект действительно не существует до этого.

Есть идеи?

Можно ли использовать:

song = Song.objects.get_or_create

Этот метод является атомарным при условии, что база данных обеспечивает уникальность аргументов ключевых слов (см. unique или unique_together). Если поля, используемые в аргументах ключевых слов, не имеют ограничения уникальности, одновременные вызовы этого метода могут привести к вставке нескольких строк с одинаковыми параметрами

Вернуться на верх