-
-
Save gengue/a914bc1540383bfa5e1374db3df10efd to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*- | |
from __future__ import absolute_import, unicode_literals | |
from rest_framework import serializers | |
from .models import User | |
class UserSerializer(serializers.ModelSerializer): | |
""" | |
User accounts serializer | |
""" | |
class Meta: | |
model = User | |
fields = ('id', 'username', 'email', 'first_name', 'last_name', | |
'is_active','is_staff', 'is_superuser', 'date_joined',) | |
read_only_fields = ('username', 'auth_token', 'date_joined',) | |
class PasswordSerializer(serializers.Serializer): | |
""" | |
Serializer for password change endpoint. | |
""" | |
old_password = serializers.CharField(required=True) | |
new_password = serializers.CharField(required=True) |
from django.conf.urls import url, include | |
from django.conf import settings | |
from django.views import defaults | |
from django.conf.urls.static import static | |
from django.contrib import admin | |
from rest_framework.documentation import include_docs_urls | |
from rest_framework.routers import DefaultRouter | |
from users.views import UserViewSet | |
router = DefaultRouter() | |
router.register(r'users', UserViewSet) | |
urlpatterns = [ | |
url(r'^admin/', admin.site.urls), | |
url(r'^api/v1/', include(router.urls)), | |
url(r'^api/v1/docs/', include_docs_urls(title='MY API')) | |
] | |
if settings.DEBUG: | |
# static/media files | |
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) | |
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) | |
import debug_toolbar | |
urlpatterns += [url(r'^__debug__/', include(debug_toolbar.urls))] |
# -*- coding: utf-8 -*- | |
from __future__ import absolute_import, unicode_literals | |
from rest_framework import viewsets, mixins, status | |
from rest_framework.response import Response | |
from rest_framework.request import Request | |
from rest_framework.decorators import list_route | |
from rest_framework.views import APIView | |
from .models import User | |
from .permissions import IsSuperuserOrIsSelf | |
from .serializers import UserSerializer, PasswordSerializer | |
class UserViewSet(mixins.ListModelMixin, | |
mixins.RetrieveModelMixin, | |
mixins.UpdateModelMixin, | |
viewsets.GenericViewSet): | |
""" | |
list: | |
Return a list of all the existing users. | |
read: | |
Return the given user. | |
me: | |
Return authenticated user. | |
""" | |
queryset = User.objects.all() | |
serializer_class = UserSerializer | |
permission_classes = (IsSuperuserOrIsSelf,) | |
@list_route(methods=['put'], serializer_class=PasswordSerializer) | |
def set_password(self, request): | |
serializer = PasswordSerializer(data=request.data) | |
if serializer.is_valid(): | |
if not user.check_password(serializer.data.get('old_password')): | |
return Response({'old_password': ['Wrong password.']}, | |
status=status.HTTP_400_BAD_REQUEST) | |
# set_password also hashes the password that the user will get | |
user.set_password(serializer.data.get('new_password')) | |
user.save() | |
return Response({'status': 'password set'}, status=status.HTTP_200_OK) | |
return Response(serializer.errors, | |
status=status.HTTP_400_BAD_REQUEST) |
Solved:
The key was finding the part of the DRF docs that indicated the route that is created when using this decorator.
http://www.django-rest-framework.org/api-guide/routers/#extra-link-and-actions
The change to my code was
@detail_route(methods=['post'], permission_classes=[IsSuperuserOrIsSelf], url_path='change-password')
def set_password(self, request, pk=None):
Thanks again for posting this gist and getting me most of the way there!
user = self.get_object()
is missing in views.py::UserViewSet::set_password
Anyone has something similar for reset password instead
@Aubrey-t, you should check this one: https://pypi.org/project/django-rest-passwordreset/
I added @nosarthur response to my code and replaced @list_route with @action and it worked!
Hi,
Thanks for it!
Could you share the code for IsSuperuserOrIsSelf
? Seems interresting to me.
Thank you all! this code is from 5 years ago I will try updated soon
Was happy to find this gist on exactly what I'm trying to accomplish. But it's not working for me.
I don't think this is my issue, because I created IsSuperuserOrIsSelf to return True and still the password isn't reset, but could you share your IsSuperuserOrIsSelf class?
I get a 200 response when I submit old and new passwords to the /users/1/ route. But the password doesn't change in the database.
I notice that you use @list_route instead of @detail_route as in the example on the DRF docs. Is this gist working for you as it is written here? Or were there more updates to get it working?
Thank you for any help you might be able to offer.