2

I have an api that will do a patch on a resource (MyUser). It validates ok and seems to save the object, however when querying the database the changes have not been saved.

class UserSignupView(generics.UpdateAPIView):
  serializer_class = MyUserSerializer

  def get_object(self, email):
    obj = MyUser.objects.get(email=email)
    self.check_object_permissions(self.request, obj)
    return obj

  def patch(self, request):
    print(request.user)
    user = self.get_object(request.user.email)
    print(user.street)
    serializer = MyUserSerializer(user, data=request.data, partial=True)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    savedUser = MyUser.objects.get(email=request.user.email)
    print(savedUser.street)
    print(serializer.data)
    return Response(serializer.data)


class MyUserSerializer(serializers.ModelSerializer):
  class Meta:
    model = MyUser
    fields = (
        'id', 'first_name', 'last_name', 'email', 'phone_number', 'street', 'locality', 'city',
        'county', 'postcode')

Looking at the print statements I get:
user@example.com
None
123 Fake Street
MyUser object

It returns the correct serialised data which contains the changes but the database does not have the changes. The database connection is ok as I can query it and make other reads/writes/etc. It's pretty much the same as the UpdateModelMixin except I've had to override the get_object with a passed in parameter.

user1584120
  • 1,169
  • 2
  • 23
  • 44
  • Since `print(savedUser.street)` prints the street correctly, your data is saved to the database. Where do you see that the object isn't saved? – dirkgroten Nov 12 '18 at 14:49
  • When I look at the actual database. The data just isn't there – user1584120 Nov 12 '18 at 15:12
  • That's not possible, you're looking in a wrong way. `MyUser.objects.get(email=request.user.email)` gives you a fresh object fetched from the database. – dirkgroten Nov 12 '18 at 15:14
  • I know, this is why I'm confused. I'm looking at the django admin page and at the actual database and they are both missing the value for street that gets printed out – user1584120 Nov 12 '18 at 15:33
  • How is `MyUser` defined? And are you looking at the Django `User` or at `MyUser`? – dirkgroten Nov 12 '18 at 15:34
  • I think there is something in the sequence of events. We've defined a hook for our authentication (in settings DEFAULT_AUTHENTICATION_CLASSES) which creates the user, it calls MyUser.objects.get_or_create(email) adds a couple more things then calls user.save(). Then it gets to the api code where it does the code defined above. Is there some sort of weird thing happening where you can't save the object again? – user1584120 Nov 12 '18 at 15:52
  • Again, I’d like to see the MyUser model. How does it relate to django.contrib.auth? – dirkgroten Nov 12 '18 at 15:54
  • Could be that the MyUser object is saved after you’ve run the patch() method with a different copy of the object. – dirkgroten Nov 12 '18 at 15:56
  • class MyUser(AbstractUser): phone_number = models.CharField(max_length=20, blank=True, null=True) street = models.CharField(blank=True, null=True, max_length=255) locality = models.CharField(blank=True, null=True, max_length=255) city = models.CharField(blank=True, null=True, max_length=255) county = models.CharField(blank=True, null=True, max_length=255) postcode = models.CharField(blank=True, null=True, max_length=8) – user1584120 Nov 12 '18 at 15:58
  • how can you ensure the correct object is saved at the right time? – user1584120 Nov 12 '18 at 15:58
  • I don’t understand how the user is created in the first place and how the `patch()` method is called – dirkgroten Nov 12 '18 at 16:02
  • Set a breakpoint in both your custom auth hook and your patch method and check the sequence of events – dirkgroten Nov 12 '18 at 16:03

1 Answers1

0

Try to override the update method and see what happens:

class MyUserSerializer(serializers.ModelSerializer):
      class Meta:
        model = MyUser
        fields = (
            'id', 'first_name', 'last_name', 'email', 'phone_number', 'street', 'locality', 'city',
            'county', 'postcode')

       def update(self, instance, validated_data):       
        instance.first_name = validated_data.get('first_name',instance.first_name)
        instance.last_name = validated_data.get('last_name',instance.last_name)
        instance.email = validated_data.get('email',instance.email)
        instance.phone_number = validated_data.get('phone_number',instance.phone_number)
        instance.street = validated_data.get('street',instance.street)
        instance.locality = validated_data.get('locality',instance.locality)
        instance.city = validated_data.get('city',instance.city)
        instance.county = validated_data.get('county',instance.county)
        instance.postcode = validated_data.get('postcode',instance.postcode)
        instance.save()
        return instance
Ogban ugot
  • 39
  • 3