Django 1.9.2 "reverse" 尝试重置密码时出错

Django 1.9.2 "reverse" error during password reset attempt

我的应用程序基于 Django 1.9.2 和 Django REST Framework 3.3.2,前端有一个单页应用程序。我必须承认我是 Django 的新手,但文档是无与伦比的。

我正在尝试实现自定义 PasswordResetForm 视图。我的策略如下:

  1. 用户在前端表单上使用 POSTs 数据(email 字符串)到 API 端点(api/v1/password/reset),当她想要重置她时密码。
  2. 如果在数据库中找到电子邮件,请发送电子邮件并return成功回复。

对于第 1 部分,这里是相关代码:

# urls.py

url(r'^api/v1/password/reset/?$', PasswordResetView.as_view(), name='password-reset-link')

-

# views.py

class PasswordResetView(GenericAPIView):
    serializer_class = PasswordResetSerializer
    permission_classes = (AllowAny,)

    def post(self, request, *args, **kwargs):
        # Use DRF serializer to validate data.
        serializer = self.get_serializer(data=request.data)

        # Ensure data is valid before proceeding.
        if serializer.is_valid() == False:
            return Response('error': serializer.errors, 'message': 'Error while attempting to reset password'}, status.HTTP_400_BAD_REQUEST)

        else:
            # Ensure the user exists.
            existing_user = get_user_model().objects.filter(
                email=serializer.validated_data.get('email')
            )

            if not existing_user:
                return Response({'error': {'code': 'email_not_in_db'}}, status.HTTP_404_NOT_FOUND)

        # Validated data fed to a child class of PasswordResetForm.
        form = UserForgotPasswordForm(serializer.validated_data)

        if form.is_valid():
            path = os.path.join(os.path.dirname(os.path.abspath(__file__ + '../../')), 'templates/registration/password_reset_email.html')

            try:
                # Save form, effectively attempting to trigger mail sending. 
                # Unfortunately an exception gets thrown!
                form.save(from_email='no-reply@abc.xyz', email_template_name=path, request=request)

                return Response({'message': 'Password reset request sent'}, status=status.HTTP_200_OK)

            except Exception as e:
                return Response({'error': str(e), 'message': 'Error while attempting to reset password'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

-

# forms.py

class UserForgotPasswordForm(PasswordResetForm):
    email = forms.EmailField(required=True, max_length=254)

    class Meta:
        model = CustomUser
        fields = ('email',)

-

# my_app/templates/registration/password_reset_email.html

{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you requested a password reset for your user account.{% endblocktrans %}

{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'password-reset-link' uidb64=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }}

{% endautoescape %}

-

但是我得到以下错误:

Reverse for 'password-reset-link' with arguments '()' and keyword arguments '{'uidb64': b'MTI1', 'token': '4g9-f370fd6ee48d90a40b67'}' not found. 1 pattern(s) tried: ['api/v1/password/reset/?$']

知道为什么吗?我错过了什么?感谢您的帮助。

在你的 html 中的 url 你传递了一个 token 和一个 uidb64:

{{ protocol }}://{{ domain }}{% url 'password-reset-link' uidb64=uid token=token %}

但是,在您的实际 url 中,您没有引用 tokenuidb64:

url(r'^api/v1/password/reset/?$', PasswordResetView.as_view(), name='password-reset-link')

我建议将您的 url 更改为:

url(r'^api/v1/password/reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', PasswordResetView.as_view(), name='password-reset-link')

您的名为 password-reset-link 的 URL 不支持您发送的关键字参数 uidb64token。这些关键字参数不仅仅是额外的数据,它们需要匹配 URL 模式中的某处。

根据错误,您的 URL 模式是:

api/v1/password/reset/?$

为了支持您想要的东西,您需要放置两个 named arguments,分别称为 <uidb64><token>。例如:

api/v1/password/reset/(?P<uidb64>[a-zA-Z0-9]+)/(?P<token>[a-zA-Z0-9]+)/?$

您必须调整正则表达式以支持 uidb64 和令牌格式。