Как создать функцию восстановления пароля с помощью фреймворка Django rest?
У меня есть приложение Django Rest Framework. И я пытаюсь создать функцию сброса пароля. Но проблема заключается в том, что некоторые функции не вызываются Django Rest Framework.
Так вот, у меня есть модуль accounts--> templates --> registration и затем html шаблоны в нем. Например:
- password_reset
- password_reset_confirm
- password_reseet_done
- password_reset_form
А в модуле счетов у меня есть файл views.py:
from django.shortcuts import render
from django.utils.http import urlsafe_base64_decode
from django.utils.encoding import force_str
from django.contrib.auth.tokens import default_token_generator
from rest_framework import generics
from .serializers import ChangePasswordSerializer
class PasswordResetConfirmView(generics.GenericAPIView):
serializer_class = ChangePasswordSerializer
def get(self, request, uidb64, token, *args, **kwargs):
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = UserModel.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
user = None
if user is not None and default_token_generator.check_token(user, token):
return render(request, 'registration/password_reset_confirm.html', {'validlink': True, 'user': user, 'uidb64': uidb64, 'token': token})
else:
return render(request, 'registration/password_reset_confirm.html', {'validlink': False})
def post(self, request, uidb64, token, *args, **kwargs):
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = UserModel.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
user = None
if user is not None and default_token_generator.check_token(user, token):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response({"message": "Password has been reset successfully."}, status=status.HTTP_200_OK)
else:
return Response({"error": "Invalid link."}, status=status.HTTP_400_BAD_REQUEST)
И файл serializers.py:
from django.utils.translation import gettext as _
from django.contrib.auth import (get_user_model, authenticate)
from rest_framework import serializers
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from django.contrib.auth import get_user_model
from django.template.loader import render_to_string
from rest_framework import serializers
from django.core.mail import send_mail
from django.urls import reverse
from django.conf import settings
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.models import User
from django.utils.encoding import force_bytes, force_str
from django.utils.http import urlsafe_base64_decode
from rest_framework import serializers
UserModel = get_user_model()
class PasswordResetSerializer(serializers.Serializer):
email = serializers.EmailField()
def validate_email(self, value):
if not UserModel.objects.filter(email=value).exists():
raise serializers.ValidationError("There is no user with this email address.")
return value
def save(self):
email = self.validated_data['email']
user = UserModel.objects.get(email=email)
# Generate token and uid
token = default_token_generator.make_token(user)
uid = urlsafe_base64_encode(force_bytes(user.pk))
# Prepare email
reset_link = self.context['request'].build_absolute_uri(
reverse('accounts:password_reset_confirm', kwargs={'uidb64': uid, 'token': token})
)
subject = "Password Reset Requested"
email_template_name = "registration/password_reset_email.html"
context = {
"email": user.email,
"reset_link": reset_link,
"user": user,
}
email = render_to_string(email_template_name, context)
# Send email
send_mail(subject, email, settings.DEFAULT_FROM_EMAIL, [user.email], fail_silently=False)
class PasswordResetConfirmSerializer(serializers.Serializer):
uidb64 = serializers.CharField()
token = serializers.CharField()
new_password = serializers.CharField(write_only=True)
re_new_password = serializers.CharField(write_only=True)
def validate(self, data):
uid = force_str(urlsafe_base64_decode(data.get('uidb64')))
self.user = User.objects.get(pk=uid)
if not default_token_generator.check_token(self.user, data.get('token')):
raise serializers.ValidationError("The reset link is invalid or has expired")
if data.get('new_password') != data.get('re_new_password'):
raise serializers.ValidationError("The two password fields didn't match.")
return data
def save(self):
self.user.set_password(self.validated_data['new_password'])
self.user.save()
А мой основной файл urls.py выглядит так:
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import include, path
from drf_spectacular.views import (SpectacularAPIView, SpectacularSwaggerView)
from rest_framework.schemas import get_schema_view
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('DierenWelzijnAdmin.urls')),
path('api-auth/', include('rest_framework.urls')),
path('schema/', get_schema_view()),
path('api/schema/', SpectacularAPIView.as_view(), name='api-schema'),
path('api/docs', SpectacularSwaggerView.as_view(url_name='api-schema'),
name='api-docs'),
path('accounts/', include(('accounts.urls','accounts'), namespace='accounts'))
А urls.py в модуле accounts выглядит так:
from django.urls import path
from rest_framework.authtoken.views import obtain_auth_token
from accounts import views
from .views import( ChangePasswordView, PasswordResetView,
PasswordResetConfirmView, send_test_email )
app_name='accounts'
urlpatterns = [
path('password-reset/', PasswordResetView.as_view(), name='password-reset'),
path('password-reset-confirm/<uidb64>/<token>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('send-test-email/', send_test_email, name='send_test_email'),
И я пытаюсь вызвать api вызов password-reset с url:
Но каждый раз я получаю эту ошибку:
NoReverseMatch в /accounts/password-reset/ Reverse for 'password_reset_confirm' не найден. 'password_reset_confirm' не является не является действительной функцией представления или именем шаблона. Метод запроса: POST-запрос URL: http://127.0.0.1:8000/accounts/password-reset/ Django Версия: 5.0.6 Тип исключения: NoReverseMatch Значение исключения: Не найден реверс для 'password_reset_confirm'. 'password_reset_confirm' не является действительной функцией представления или именем шаблона.
Вопрос: как вызвать api вызов: password-reset без ошибки?