2016-04-22 4 views
1

я в настоящее время имеют следующие Viewset:Django REST Framework perform_create: Вы не можете назвать `.save()` после получения доступа к `serializer.data`

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

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

Со следующими сериализаторов:

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

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

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. 

Я не вижу, где бы я редактировал объект serializer.data. Есть ли что-то, что мне не хватает, что приведет к этому редактированию? Как я могу устранить эту ошибку?

+1

Мне редко нужно было переопределить метод в представлении, и когда мне это нужно, он часто заканчивался хаками и копировал пасты из исходного переопределенного кода. Как правило, лучше использовать материал в сериализаторе, когда это возможно. Невозможно ли вы поместить свой материал в метод 'create()' сериализатора? – pasztorpisti

+0

Я согласен с тем, что я должен пересмотреть, как я это делаю. Тем не менее, я все еще чувствую, что это может быть признаком проблемы. Я взял этот код прямо из документации DRF. –

ответ

2

Вам вообще не нужно звонить 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 

Чтобы отправить дополнительные данные сериализатора при сохранении (например, чтобы установить компанию, или установить пользователь и т.д.), используйте переопределение как это:

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

Для получения более подробной информации я бы просмотрел исходный код DRF и посмотрел, что он делает. это очень хорошо написано и понятно.

Ваш комментарий еще не задан для обсуждения much больше. Вы говорите, что хотите добавить дополнительные данные в таблицу «join» между исполнителями и пользователем. Это можно сделать, но это совершенно другая тема, и вы в конечном итоге вручную управляете отношениями. Кроме того, читайте о вложенных перезаписываемых сериализаторах, это большая тема и даже более ручной труд.

+0

Удаление is_valid по-прежнему вызывает ту же ошибку, однако, мешает мне делать то, что вы сделали в своем втором примере. Я действительно хочу добавить в таблицу соединений в конечном счете, но мне нужно сначала решить эту проблему, я думаю. Благодарим вас за дополнительные комментарии о вложенном записываемом сериализаторе; Я буду исследовать. –

+0

Записываемые вложенные представления - это именно то, что мне нужно. Спасибо за ваш комментарий. Тем не менее, я все еще чувствую, что исходный вопрос может быть признаком проблемы. Я взял этот код прямо из документации DRF. –

+0

@KerryRitter. Вложенные представления, которые можно записывать, всегда должны обрабатываться с помощью специального кода, как правило, в 'create()' и/или 'update()' serial() 'последовательного интерфейса: http://www.django-rest-framework.org/api-guide/ отношения/# записываемые-вложенные сериализаторы – pasztorpisti

Смежные вопросы