7

I want to create an API where user can update their profile. In my case, a user can update his/her username and password. To change his/her profile, an API link should be /api/change/usernameOfThatUser. When I use a non-existing username in the link, I still get the userProfileChange API page, and the input boxes are not filled with previous data. How can I solve this?

serializers.py

User = get_user_model()

class UserProfileChangeSerializer(ModelSerializer):
    username = CharField(required=False, allow_blank=True, initial="current username")
    class Meta:
        model = User
        fields = [
            'username',
            'password',
        ]

    def update(self, instance, validated_data):
        instance.username = validated_data.get('username',instance.username)
        print('instance of username',instance.username)
        return instance 

views.py

class UserProfileChangeAPIView(UpdateAPIView):
    serializer_class = UserProfileChangeSerializer
    lookup_field = 'username'

urls.py

  url(r'^change/(?P<username>[\w-]+)$', UserProfileChangeAPIView.as_view(), name='changeProfile'),
jape
  • 2,861
  • 2
  • 26
  • 58
pri
  • 620
  • 2
  • 9
  • 20
  • What you want to happen when you use non existed username in the link? – Arun Ghosh Jul 18 '16 at 10:55
  • Your question doesn't make sense. "How can i solve this?" << you need to tell us what behavior is expected here because the one you have is the one I'd expect. – Linovia Jul 18 '16 at 11:32
  • suppose my username is michael then what i want is if i want to change my username then i would do /api/users/michael and the page will be shown with username field and password field. In username field, my name will be already filled in, i would then edit it and save. – pri Jul 18 '16 at 11:40

1 Answers1

10

Maybe try doing something like this instead in your views.py?

from rest_framework import generics, mixins, permissions

User = get_user_model()

class UserIsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.id == request.user.id

class UserProfileChangeAPIView(generics.RetrieveAPIView,
                               mixins.DestroyModelMixin,
                               mixins.UpdateModelMixin):
    permission_classes = (
        permissions.IsAuthenticated,
        UserIsOwnerOrReadOnly,
    )
    serializer_class = UserProfileChangeSerializer
    parser_classes = (MultiPartParser, FormParser,)

    def get_object(self):
        username = self.kwargs["username"]
        obj = get_object_or_404(User, username=username)
        return obj

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

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

This will give you all of the existing data for the user based on the username passed in the url. If the username does not exist, it will raise a 404 error. You can also update or delete the object.

jape
  • 2,861
  • 2
  • 26
  • 58
  • Password is shown in sha256$24000$ form. How can i show empty box only for password? Any authenticated user can open the profile edit page of other user. So can you enlighten me the concept to solve this? – pri Jul 19 '16 at 01:09
  • 1
    @pri If you take a look at the code now, it will make sure the user can only edit their own profile. It was a permission change. I would create a separate function for password change functionality. Do you need help with that as well? – jape Jul 19 '16 at 12:23
  • @pri You can take a look at this for hashing the password: http://stackoverflow.com/questions/27586095/why-isnt-my-django-user-models-password-hashed – jape Jul 19 '16 at 12:38
  • Thanks I will look at hashing the password. – pri Jul 19 '16 at 15:13