title: Django - KeyError: 'profile' - Trying to save the user profile with DRF and Ajax
body: <p>I'm trying to save the user profile data with DRF and Ajax but I have an error KeyError.</p>
  
  <p>I was reading the DRF docs, especifically this part: <a href="https://www.django-rest-framework.org/api-guide/serializers/#writable-nested-representations" rel="nofollow noreferrer">Writable Nested Representations</a> that is what i want but, doesn't work for me.</p>
  
  <p>I hope you can help me</p>
  
  <p>this is my <strong><em>serializer.py</em></strong></p>
  
  <pre><code>class ProfileSerializer(serializers.ModelSerializer):
  
      class Meta:
          model = Profile
          fields = ('user', 'avatar', 'dob', 'headline',
                  'country', 'location', 'cp', 'background',
                  'facebook', 'twitter', 'github', 'website',)
          read_only_fields = ('user', ) # I tried removing this part but, not work (In some forums say it)
  
  
  class UserSerializer(serializers.ModelSerializer):
      profile = ProfileSerializer()
  
      class Meta:
          model = User
          exclude = ('password', 'is_superuser', 'is_staff', 'is_active', 'user_permissions', 'groups', 'last_login',)
          read_only_fields = ('username', 'email', 'date_joined', )
  
      def update(self, instance, validated_data):
          profile_data = validated_data.pop('profile')
          profile = instance.profile
  
          instance.username = validated_data.get('username', instance.username)
          instance.first_name = validated_data.get('first_name', instance.first_name)
          instance.last_name = validated_data.get('last_name', instance.last_name)
          instance.save()
  
          profile.avatar = profile_data.get('avatar', profile.avatar)
          profile.dob = profile_data.get('dob', profile.dob)
          profile.headline = profile_data.get('headline', profile.headline)
          profile.country = profile_data.get('country', profile.country)
          profile.location = profile_data.get('location', profile.location)
          profile.cp = profile_data.get('cp', profile.cp)
          profile.background = profile_data.get('background', profile.background)
          profile.facebook = profile_data.get('facebook', profile.facebook)
          profile.twitter = profile_data.get('twitter', profile.twitter)
          profile.github = profile_data.get('github', profile.github)
          profile.website = profile_data.get('website', profile.website)
  
          profile.save()
  
          return instance
  </code></pre>
  
  <p>my <strong><em>views.py</em></strong></p>
  
  <pre><code>class ProfileRetrieveAPIView(generics.RetrieveUpdateDestroyAPIView):
      queryset = User.objects.all()
      serializer_class = UserSerializer
      permission_classes = (IsAuthenticatedOrReadOnly, IsAuthenticatedOrReadOnly, )
      lookup_field = 'username'
  
      def retrieve(self, request, *args, **kwargs):
          super(ProfileRetrieveAPIView, self).retrieve(request, args, kwargs)
          instance = self.get_object()
          serializer = self.get_serializer(instance)
          data = serializer.data
          response = {
              "message": "Successfully retrieved",
              "data": data,
              "status_code": status.HTTP_200_OK
          }
          return Response(response)
  
      def patch(self, request, *args, **kwargs):
          super(ProfileRetrieveAPIView, self).patch(request, args, kwargs)
          instance = self.get_object()
          serializer = self.get_serializer(instance)
          data = serializer.data
          response = {
              "message": "Perfil actualizado con éxito",
              "data": data,
              "status": status.HTTP_200_OK
          }
          return Response(response, status=status.HTTP_200_OK)
  </code></pre>
  
  <p>and my <strong>ajax.js</strong></p>
  
  <pre><code>$("#saveProfile").click(function(e) {
      e.preventDefault();
  
      var profileData = {
        'avatar': $("#avatar").val(),
        'first_name': $("#first_name").val(),
        'last_name': $("#last_name").val(),
        'country': $("#country").val(),
        'location': $("#location").val(),
        'cp': $("#postal_code").val(),
        'headline': $("#headline").val(),
        'dob': $("#dob").val(),
        'facebook': $("#facebook").val(),
        'twitter': $("#twitter").val(),
        'github': $("#github").val(),
        'website': $("#website").val(),
      }
      $.ajax({
        type: 'PATCH',
        url: "{% url 'profiles:api_profile' username=request.user.username %}",
        data: JSON.stringify(profileData),
        contentType: 'application/json; charset=utf-8',
        success: function(res) {
          console.log(res.data);
        },
        error: function(res) {
          console.log(res);
        }
      });
    });
  </code></pre>
  
  <p>**** update, I added the models.py** </p>
  
  <pre><code>class Profile(TimeStampedModel):
  
      user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name="profile", on_delete=models.CASCADE)
      avatar = ThumbnailerImageField(upload_to=user_directory_path, blank=True, validators=[validate_image_extension])
      dob = models.DateField(_("Date of Birth"), blank=True, null=True)
      headline = models.CharField(_("Headline"), max_length=255)
      country = models.CharField(_("Country"), max_length=100, blank=True)
      location = models.CharField(_("Location"), max_length=255, blank=True)
      cp = models.CharField(_("Postal Code"), max_length=5, blank=True)
      #sector = models.TextField(_("Sector"))
      background = ThumbnailerImageField(upload_to='photos/', blank=True, validators=[validate_image_extension])
      #contact information
      facebook = models.URLField(_("Facebook"), max_length=200, blank=True, null=True)
      twitter = models.URLField(_("Twitter"), max_length=200, blank=True, null=True)
      github = models.URLField(_("GitHub"), max_length=200, blank=True, null=True)
      website = models.URLField(_("Website"), max_length=200, blank=True, null=True)
      enterprise = models.BooleanField(_("Is enterprise account?"), default=False)
  
  
      def __str__(self):
          return self.user.get_full_name()
  </code></pre>
  
  <p>and other models.py</p>
  
  <pre><code>class TimeStampedModel(models.Model):
      """
      Un modelo base abstracto que provee de campos predeterminados
      para que no sean repetitivos, se puede heredar de este modelo
      a todos los demás para excluir la repeticion de los campos
      ``created_at`` and ``updated_at``.
      """
      created_at = models.DateTimeField(_("Created Date"), auto_now_add=True)
      updated_at = models.DateTimeField(_("Updated Date"), auto_now=True)
  
      class Meta:
          abstract = True
  
  class User(AbstractUser):
  
      role = models.BooleanField(_("Enterprise Account"), default=False)
  </code></pre>
  
  <p>When I press the save button the server gaves me this error:</p>
  
  <pre><code>  File "C:\Users\a_niu\.virtualenvs\Vinculacion-S2cHiiVR\lib\site-packages\rest_framework\generics.py", line 288, in patch
      return self.partial_update(request, *args, **kwargs)
    File "C:\Users\a_niu\.virtualenvs\Vinculacion-S2cHiiVR\lib\site-packages\rest_framework\mixins.py", line 82, in partial_update
      return self.update(request, *args, **kwargs)
    File "C:\Users\a_niu\.virtualenvs\Vinculacion-S2cHiiVR\lib\site-packages\rest_framework\mixins.py", line 68, in update
      self.perform_update(serializer)
    File "C:\Users\a_niu\.virtualenvs\Vinculacion-S2cHiiVR\lib\site-packages\rest_framework\mixins.py", line 78, in perform_update
      serializer.save()
    File "C:\Users\a_niu\.virtualenvs\Vinculacion-S2cHiiVR\lib\site-packages\rest_framework\serializers.py", line 208, in save
      self.instance = self.update(self.instance, validated_data)
    File "C:\Users\a_niu\Desktop\practicas\Django\Vinculacion\app\profiles\serializers.py", line 24, in update
      profile_data = validated_data.pop('profile')
  KeyError: 'profile'
  </code></pre>