Django REST Framework perform_create: You cannot c

2019-07-11 07:51发布

问题:

I currently have the following viewset:

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

    def perform_create(self, serializer):
        if serializer.is_valid():
            serializer.save()

With the following serializers:

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...)

I am getting the following error:

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. 

I don't see where I would be editing the serializer.data object. Is there something I am missing that would cause this edit? How can I resolve this error?

回答1:

You don't need to call is_valid there at all. When you do an update the serializer is initialized with the model instance (based of the pk in the route, e.g PATCH /artists/{3}/). You would call is_valid() if you are passing data to the serializer as in:

ser = MySerializer(data=request.data) # validate incoming post, etc
ser.is_valid(raise_exceptions=True)
data = ser.validated_data

To send additional data to the serializer when saving (e.g. to set a company, or set a user, etc), use an override like this:

def perform_create(self, serializer):
    serializer.save(company=self.request.user.company)

For more details, I would browse the DRF source code and see what it is doing. it's very well written and clear.

Your comment indicates another question which is much bigger. You say you want to add additional data to the "join" table between artists and user. This can be done, but is a whole different topic and you end up manually managing the relationship. Also, read up on nested writable serializers, it's a big topic and even more manual labor.



回答2:

If you are using PyCharm and you were debugging some code check if you haven't got calling serializer.data in your watches. It call .data everytime your debugger stop in context that given serializer appear even if you don't call it explicit in your code.