2016-08-23 1 views
0

Je suis en train de mettre à jour un objet de profil avec méthode post, mais je reçois un message d'erreur lorsque vous essayez de sauver mon sérialiseur:django cadre de repos sauver sérialiseur échouer avec méthode post

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. 

Mon point de vue:

class SettingsProfileView(APIView): 
    """ 
    Get and update user profile 
    """ 
    queryset = models.UserProfile.objects.all() 
    serializer_class = serializers.UserProfileSerializer 

    renderer_classes = [TemplateHTMLRenderer] 
    template_name = 'base_/settings/profile.html' 

    def get_object(self, pk): 
     try: 
      return models.UserProfile.objects.get(pk=pk) 
     except models.UserProfile.DoesNotExist: 
      raise Http404 

    def get(self, request, format=None): 
     if not request.user.is_authenticated: 
      return Response({"error": _("User is not connected")}, status=status.HTTP_511_NETWORK_AUTHENTICATION_REQUIRED) 

     try: 
      profile = request.user.profile 
     except models.UserProfile.DoesNotExist: 
      profile = models.UserProfile(user=request.user) 
      profile.key_name = request.user.username 
      profile.save() 

     profile = self.get_object(request.user.profile.id) 
     serializer = serializers.UserProfileSerializer(profile) 
     return Response({'serializer': serializer, 'profile': profile}) 


    def post(self, request, format=None): 
     serializer = serializers.UserProfileSerializer(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) 

L'erreur est survenue dans cette partie: serializer.save() dans ma méthode post. Est-ce parce que le sérialiseur accède aux données dans sa méthode d'instanciation? Mon sérialiseur est très basique, il n'a pas de code spécial:

class UserProfileSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = UserProfile 
     fields = ('user', 'coachs', 'is_coach', 'gender', 'weight', 'height', 'visibility',) 

Peut-être que le problème vient du fait que j'utilise Methode après au lieu de la mise à jour?

EDIT (après post @pleasedontbelong):

J'ai essayé avec vue générique:

class SettingsProfileView(generics.GenericAPIView): 

mais la méthode de mise à jour ne se déclenche pas (parce que je viens d'un poste HTML), donc je devais manuellement augmenter la méthode de mise à jour comme ça:

def post(self, request, *args, **kwargs): 
     return self.update(request, *args, **kwargs) 

def update(self, request, *args, **kwargs): 
     partial = kwargs.pop('partial', False) 
     instance = self.get_object(request.user.profile.id) 
     serializer = self.get_serializer(instance, data=request.data, partial=partial) 
     serializer.is_valid(raise_exception=True) 
     self.perform_update(serializer) 
     return Response(serializer.data) 

Mais l'erreur est toujours la même. Je ne trouve aucun exemple où un objet est mis à jour avec le reste de django par la méthode post. Est-ce parce que ce n'est pas une bonne façon de procéder?

Répondre

0

Après des heures de débogage, il semble que le problème provient des points d'arrêt de Visual Studio. Après avoir supprimé les points d'arrêt, cela fonctionne bien. Peut-être que Visual Studio essaie de lire dans serializer.data puis les affecte.

0

Il est préférable d'utiliser des vues génériques, il vous empêche de réécrire tout le code. Mais si vous préférez le faire manuellement, vous pouvez toujours vérifier le code source pour vérifier comment il est fait:

https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py#L61-L78

class UpdateModelMixin(object): 
    """ 
    Update a model instance. 
    """ 
    def update(self, request, *args, **kwargs): 
     partial = kwargs.pop('partial', False) 
     instance = self.get_object() 
     serializer = self.get_serializer(instance, data=request.data, partial=partial) 
     serializer.is_valid(raise_exception=True) 
     self.perform_update(serializer) 
     return Response(serializer.data) 

    def perform_update(self, serializer): 
     serializer.save() 

    def partial_update(self, request, *args, **kwargs): 
     kwargs['partial'] = True 
     return self.update(request, *args, **kwargs) 

vous devez passer l'instance UserProfile au sérialiseur

BTW: vous devriez/doit utiliser PUT ou PATCH pour la mise à jour, POST pour créer des objets.

Hope this helps :)

+0

Merci @pleasedontbelong J'ai édité la question avec vos suggestions, mais je dois toujours la même erreur. – Ben