简体   繁体   English

Django rest_framework 忘记密码

[英]Django rest_framework forgot password

I'm newbie in Django I have a trouble with this: I've already make API for 'request-reset-email', 'password-reset' and 'password-reset-complete' Here are the code: file: urls.py我是 Django 的新手 我遇到了麻烦:我已经为“请求重置电子邮件”、“密码重置”和“密码重置完成”制作了 API 这是代码:文件:网址。 py

from django.urls import path
from .views import *
from django.contrib.auth import views as auth_view
from rest_framework_simplejwt.views import (
    TokenObtainSlidingView,
    TokenRefreshSlidingView,
)
urlpatterns=[
    path('register/', RegisterView.as_view(), name="register"),
    path('login/', LoginAPIView.as_view(), name="login"),
    path('email-verify/', VerifyEmail.as_view(), name="email-verify"),
    path('token/refresh/', TokenRefreshSlidingView.as_view(), name='token_refresh'),
    path('request-reset-email/',RequestPasswordResetEmail.as_view(), name='request-reset-email'),
    path('password-reset/<uidb64>/<token>/',PasswordTokenCheckAPIView.as_view(),name='password-reset'),
    path('password-reset-complete/',SetNewPasswordAPIView.as_view(),name='password-reset-complete')
]

file Views.py:文件 Views.py:

from django.shortcuts import render
from rest_framework import exceptions, generics, serializers
from rest_framework.response import Response
from rest_framework import status
from .models import *
from .serializers import *
from rest_framework_simplejwt.tokens import RefreshToken
from .utils import *
from django.contrib.sites.shortcuts import get_current_site
from django.urls import reverse
import jwt
from django.conf import settings
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils.encoding import smart_str, force_str, smart_bytes, DjangoUnicodeDecodeError
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
# Create your views here.
class RegisterView(generics.GenericAPIView):
    queryset = User.objects.all()
    serializer_class=RegisterSerializer
    def post(self, request):
        user = request.data
        serializer = self.serializer_class(data=user)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        user_data = serializer.data

        user= User.objects.get(email=user_data['email'])
        token=RefreshToken.for_user(user).access_token

        current_site=get_current_site(request).domain
        realtivelink = reverse('email-verify')
        
        absurl='http://'+current_site+realtivelink+"?token="+ str(token)
        email_body='Hi '+ user.email+ ' Use link below to verify your email \n' + absurl
        data={'email_body':email_body,'to_email':user.email,'email_subject':'Verify your email'}
        Util.send_email(data)
        return Response(user_data,status= status.HTTP_201_CREATED)

class VerifyEmail(generics.GenericAPIView):
    def get(self,request):
        token= request.GET.get('token')
        try:
            payload=jwt.decode(token,settings.SECRET_KEY,algorithms='HS256')
            user=User.objects.get(id=payload['user_id'])

            if not user.is_verified:
                user.is_verified=True
                user.save()
            return Response({'email':'Successfully activated'},status= status.HTTP_200_OK)
        except jwt.ExpiredSignatureError as indentifier:
            return Response({'email':'Activation expired'},status= status.HTTP_400_BAD_REQUEST)
        except jwt.exceptions.DecodeError as indentifier:
            return Response({'email':'Invalid token'},status= status.HTTP_400_BAD_REQUEST)


class LoginAPIView(generics.GenericAPIView):
    queryset = User.objects.all()
    serializer_class = LoginSerializers
    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        return Response(serializer.data,status=status.HTTP_200_OK )

class RequestPasswordResetEmail(generics.GenericAPIView):
    queryset = User.objects.all()
    serializer_class=ResetPasswordViaEmailSerializer
    def post(self, request):

        serializer = self.serializer_class(data=request.data)
        email = request.data['email']

        if User.objects.filter(email=email).exists():
            user = User.objects.get(email=email)
            uidb64 = urlsafe_base64_encode(smart_bytes(user.id) )
            token = PasswordResetTokenGenerator().make_token(user)

            current_site=get_current_site(request=request).domain
            realtivelink = reverse('password-reset',kwargs={'uidb64':uidb64,'token':token})
                
            absurl='http://'+current_site+realtivelink
            email_body='Hi, \nUse link below to reset your password \n' + absurl
            data={'email_body':email_body,'to_email':user.email,'email_subject':'Reset your password'}
            Util.send_email(data)
        return Response({'successfully':'check your email to reset your password'},status=status.HTTP_200_OK)

class PasswordTokenCheckAPIView(generics.GenericAPIView):
    def get(self, request, uidb64,token):
        try:
            id= smart_str(urlsafe_base64_decode(uidb64))
            user= User.objects.get(id=id)
            if not PasswordResetTokenGenerator().check_token(user,token):
                return Response({'error':'token is not valid, please check the new one'},status=status.HTTP_401_UNAUTHORIZED)
            return Response({'sucess':True, 'message':'Credential Valid','uidb64':uidb64, 'token':token},status=status.HTTP_200_OK)


        except DjangoUnicodeDecodeError as indentifier:
            return Response({'error':'token is not valid, please check the new one'},status=status.HTTP_401_UNAUTHORIZED)

class SetNewPasswordAPIView(generics.GenericAPIView):
    queryset = User.objects.all()
    serializer_class=ResetPassWordSerializer

    def patch(self, request):
        serializer=self.serializer_class(data=request.data)

        serializer.is_valid(raise_exception=True)

        return Response({'sucess':True, 'message':'Password is reset successfully'},status=status.HTTP_200_OK)

APIs've already worked. API 已经发挥作用。 But I want to make the "PasswordTokenCheckAPIView" have a templete for user to enter the new password and confirm it.但我想让“PasswordTokenCheckAPIView”有一个模板供用户输入新密码并确认。 So, could you please to give me some way to do this?那么,你能给我一些方法吗? I've tried to use django.contrib.auth.PasswordResetConfirmView, it appears the template when I click the link I received in mail, but when I confirm change password, there is error我尝试使用 django.contrib.auth.PasswordResetConfirmView,当我点击我在邮件中收到的链接时它会出现模板,但是当我确认更改密码时,出现错误

from django.urls import path
from .views import *
from django.contrib.auth import views as auth_view
from rest_framework_simplejwt.views import (
    TokenObtainSlidingView,
    TokenRefreshSlidingView,
)
urlpatterns=[
    path('register/', RegisterView.as_view(), name="register"),
    path('login/', LoginAPIView.as_view(), name="login"),
    path('email-verify/', VerifyEmail.as_view(), name="email-verify"),
    path('token/refresh/', TokenRefreshSlidingView.as_view(), name='token_refresh'),
    path('request-reset-email/',RequestPasswordResetEmail.as_view(), name='request-reset-email'),
    path('password-reset/<uidb64>/<token>/',auth_view.PasswordResetConfirmView.as_view(),name='password-reset'),
    path('password_reset_complete/',auth_view.PasswordResetCompleteView.as_view(),name='password-reset-complete')
]

the error: Reverse for 'password_reset_complete' not found.错误:找不到“password_reset_complete”的反向。 'password_reset_complete' is not a valid view function or pattern name. 'password_reset_complete' 不是有效的视图 function 或模式名称。

Thank you very much!非常感谢你!

Change改变

path('password_reset_complete/',auth_view.PasswordResetCompleteView.as_view(),name='password-reset-complete')

to

path('password_reset_complete/',auth_view.PasswordResetCompleteView.as_view(),name='password_reset_complete')

Django reverse checks for name in the path. Django 反向检查路径中的名称。

Can you share your Serializers pls你能分享你的序列化程序吗

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM