Django REST Framework perform_create:访问`serializer.data`后无法调用`.save()`

Ker*_*ter 9 django django-rest-framework

我目前有以下视图集:

class ArtistProfileViewSet(viewsets.ModelViewSet):
    queryset = ArtistProfile.objects.all()
    serializer_class = ArtistProfileSerializer

    def perform_create(self, serializer):
        if serializer.is_valid():
            serializer.save()
Run Code Online (Sandbox Code Playgroud)

使用以下序列化程序:

class SimpleArtistTrackSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = ArtistTrack
        fields = (...my fields...)


class ArtistProfileSerializer(serializers.HyperlinkedModelSerializer):
    owners = UserSerializer(many=True, required=False)
    tracks = SimpleArtistTrackSerializer(many=True, required=False)

    class Meta:
        model = ArtistProfile
        fields = (...my fields...)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

AssertionError: You cannot call `.save()` after accessing `serializer.data`.If you need to access data before committing to the database then inspect 'serializer.validated_data' instead. 
Run Code Online (Sandbox Code Playgroud)

我不知道在哪里编辑 serializer.data 对象。有什么我遗漏的东西会导致这个编辑吗?我该如何解决这个错误?

Raf*_*fał 13

如果您正在使用 PyCharm 并且正在调试一些代码,请检查您是否没有serializer.data在调试器中调用“watches”。.data每当您的调试器在给定的序列化程序出现的给定上下文(断点)中停止时,它都会调用,即使您没有serializer.data在代码中调用它explicit( )。


And*_*ker 10

你根本不需要在is_valid那里打电话。当您进行更新时,序列化程序将使用模型实例进行初始化(基于pk路由中的 ,例如PATCH /artists/{3}/)。is_valid()如果您将数据传递给序列化程序,您将调用,如下所示:

ser = MySerializer(data=request.data) # validate incoming post, etc
ser.is_valid(raise_exceptions=True)
data = ser.validated_data
Run Code Online (Sandbox Code Playgroud)

要在保存时向序列化程序发送附加数据(例如设置公司或设置用户等),请使用如下覆盖:

def perform_create(self, serializer):
    serializer.save(company=self.request.user.company)
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,我将浏览 DRF 源代码并查看它在做什么。它写得很好,很清楚。

您的评论指出的另一个问题是很多大。你说你想在艺术家和用户之间的“加入”表中添加额外的数据。这可以完成,但这是一个完全不同的主题,您最终需要手动管理关系。此外,阅读嵌套的可写序列化程序,这是一个很大的话题,甚至更多的体力劳动。