django rest框架简单的post方法与两个相关的对象

hrirmatl  于 2023-10-21  发布在  Go
关注(0)|答案(1)|浏览(91)

我正在尝试创建一个简单的Django Rest Framework应用程序,用于存储监听历史,其中包括ListeningHistory,Track和Artist模型。每个ListeningHistory记录与一个曲目相关,并且每个曲目与一个或多个艺术家相关。如果曲目或艺术家已经存在,它应该重新使用该记录,而不是尝试创建一个新的。
models.py:

class Artist(models.Model):
    name = models.CharField(max_length=255, unique=True)

class Track(models.Model):
    title = models.CharField(max_length=255, unique=True)
    artists = models.ManyToManyField(Artist)
    album = models.CharField(max_length=255, null=True)

class ListeningHistory(models.Model):
    class Meta:
        ordering = ['-played_at']

    played_at = models.DateTimeField(unique=True)
    track = models.ForeignKey(Track, on_delete=models.PROTECT)

serializers.py:

class ArtistSerializer(serializers.ModelSerializer):
    class Meta:
        model = Artist
        fields = '__all__'

class TrackSerializer(serializers.ModelSerializer):
    artists = ArtistSerializer(many=True)

    class Meta:
        model = Track
        fields = '__all__'

    def create(self, validated_data):
        artists_data = validated_data.pop('artists')
        track, created = Track.objects.get_or_create(**validated_data)
        artists = [Artist.objects.get_or_create(name=artist_data['name'])[0] for artist_data in artists_data]
        track.artists.set(artists)
        return track

class ListeningHistorySerializer(serializers.ModelSerializer):
    track = TrackSerializer()

    class Meta:
        model = ListeningHistory
        fields = '__all__'

    def create(self, validated_data):
        track_data = validated_data.pop('track')
        artists_data = track_data.pop('artists')
        track, created = Track.objects.get_or_create(**track_data)
        artists = [Artist.objects.get_or_create(name=artist_data['name'])[0] for artist_data in artists_data]
        track.artists.set(artists)
        listening_history = ListeningHistory.objects.create(track=track, **validated_data)
        return listening_history

views.py:

class ListeningHistoryAPIView(APIView):
    def post(self, request):
        serializer = ListeningHistorySerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

第一个帖子可以工作,但是当我尝试使用现有的曲目和/或艺术家发布另一个记录时,序列化器验证失败。什么才是解决这个问题的正确方法?

kuhbmx9i

kuhbmx9i1#

您面临的问题与如何在序列化器中处理现有轨道和艺术家的创建有关。为了确保序列化程序正常工作,您应该更新TrackSerializerListeningHistorySerializer,以正确处理现有记录。您可以使用get方法检索现有记录,并且仅在记录不存在时才创建新记录。以下是如何修改序列化器
在您的TrackSerializer中,修改create方法如下:

class TrackSerializer(serializers.ModelSerializer):
    artists = ArtistSerializer(many=True)

    class Meta:
        model = Track
        fields = '__all__'

    def create(self, validated_data):
        artists_data = validated_data.pop('artists')
        
        # Check if the track already exists
        track, created = Track.objects

相关问题