安装django-password-reset Django后的NoReverseMatch

时间:2016-05-24 12:42:17

标签: python django

我试图在我的项目(password_forgot)中安装brutasse/django-password-reset(来自github)作为应用程序。不幸的是,每当我在忘记密码页面(login/e-mail)上传递正确的.../password_forgot/recover/时,我都会收到以下错误:

  

异常类型:NoReverseMatch异常值:反向   带参数的'password_reset_sent'   '(' ImlkZWFsbmEuc3VraWVua2FAb25ldC5wbCI:1b5BRG:UUCzmKT_IB4UjnLs59AzXDuDuoI ')'   和找不到关键字参数“{}”。尝试了0种模式:[]

这是追溯:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\handlers\base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\handlers\base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\views\generic\base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\views\generic\base.py", line 88, in dispatch
    return handler(request, *args, **kwargs)
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\views\generic\edit.py", line 222, in post
    return self.form_valid(form)
  File "C:\Users\kempa\Desktop\MESproject\MESproject\password_forgot\views.py", line 111, in form_valid
    return super(Recover, self).form_valid(form)
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\views\generic\edit.py", line 108, in form_valid
    return HttpResponseRedirect(self.get_success_url())
  File "C:\Users\kempa\Desktop\MESproject\MESproject\password_forgot\views.py", line 66, in get_success_url
    return reverse(self.success_url_name, args=[self.mail_signature])
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\urlresolvers.py", line 600, in reverse
    return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\urlresolvers.py", line 508, in _reverse_with_prefix
    (lookup_view_s, args, kwargs, len(patterns), patterns))
django.core.urlresolvers.NoReverseMatch: Reverse for 'password_reset_sent' with arguments '('ImlkZWFsbmEuc3VraWVua2FAb25ldC5wbCI:1b5BRG:UUCzmKT_IB4UjnLs59AzXDuDuoI',)' and keyword arguments '{}' not found. 0 pattern(s) tried: []
[24/May/2016 14:27:58] "POST /password_forgot/recover/ HTTP/1.1" 500 96297

我添加的网址:     url(r'^password_forgot/', include('password_forgot.urls', namespace='password_forgot'))

观点:

import datetime

from django.conf import settings
from django.core import signing
from django.core.mail import send_mail
from django.core.urlresolvers import reverse, reverse_lazy
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect
from django.template import loader
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views import generic
from django.views.decorators.debug import sensitive_post_parameters

try:
    from django.contrib.sites.shortcuts import get_current_site
except ImportError:
    from django.contrib.sites.models import get_current_site

from .forms import PasswordRecoveryForm, PasswordResetForm
from .signals import user_recovers_password
from .utils import get_user_model, get_username


class SaltMixin(object):
    salt = 'password_recovery'
    url_salt = 'password_recovery_url'


def loads_with_timestamp(value, salt):
    """Returns the unsigned value along with its timestamp, the time when it
    got dumped."""
    try:
        signing.loads(value, salt=salt, max_age=-1)
    except signing.SignatureExpired as e:
        age = float(str(e).split('Signature age ')[1].split(' >')[0])
        timestamp = timezone.now() - datetime.timedelta(seconds=age)
        return timestamp, signing.loads(value, salt=salt)


class RecoverDone(SaltMixin, generic.TemplateView):
    template_name = 'password_forgot/reset_sent.html'

    def get_context_data(self, **kwargs):
        ctx = super(RecoverDone, self).get_context_data(**kwargs)
        try:
            ctx['timestamp'], ctx['email'] = loads_with_timestamp(
                self.kwargs['signature'], salt=self.url_salt,
            )
        except signing.BadSignature:
            raise Http404
        return ctx
recover_done = RecoverDone.as_view()


class Recover(SaltMixin, generic.FormView):
    case_sensitive = True
    form_class = PasswordRecoveryForm
    template_name = 'password_forgot/recovery_form.html'
    success_url_name = 'password_reset_sent'
    email_template_name = 'password_forgot/recovery_email.txt'
    email_subject_template_name = 'password_forgot/recovery_email_subject.txt'
    search_fields = ['username', 'email']

    def get_success_url(self):
        return reverse(self.success_url_name, args=[self.mail_signature])

    def get_context_data(self, **kwargs):
        kwargs['url'] = self.request.get_full_path()
        return super(Recover, self).get_context_data(**kwargs)

    def get_form_kwargs(self):
        kwargs = super(Recover, self).get_form_kwargs()
        kwargs.update({
            'case_sensitive': self.case_sensitive,
            'search_fields': self.search_fields,
        })
        return kwargs

    def get_site(self):
        return get_current_site(self.request)

    def send_notification(self):
        context = {
            'site': self.get_site(),
            'user': self.user,
            'username': get_username(self.user),
            'token': signing.dumps(self.user.pk, salt=self.salt),
            'secure': self.request.is_secure(),
        }
        body = loader.render_to_string(self.email_template_name,
                                       context).strip()
        subject = loader.render_to_string(self.email_subject_template_name,
                                          context).strip()
        send_mail(subject, body, settings.DEFAULT_FROM_EMAIL,
                  [self.user.email])

    def form_valid(self, form):
        self.user = form.cleaned_data['user']
        self.send_notification()
        if (
            len(self.search_fields) == 1 and
            self.search_fields[0] == 'username'
        ):
            # if we only search by username, don't disclose the user email
            # since it may now be public information.
            email = self.user.username
        else:
            email = self.user.email
        self.mail_signature = signing.dumps(email, salt=self.url_salt)
        return super(Recover, self).form_valid(form)
recover = Recover.as_view()


class Reset(SaltMixin, generic.FormView):
    form_class = PasswordResetForm
    token_expires = 3600 * 48  # Two days
    template_name = 'password_forgot/reset.html'
    success_url = reverse_lazy('password_reset_done')

    @method_decorator(sensitive_post_parameters('password1', 'password2'))
    def dispatch(self, request, *args, **kwargs):
        self.request = request
        self.args = args
        self.kwargs = kwargs
        self.user = None

        try:
            pk = signing.loads(kwargs['token'], max_age=self.token_expires,
                               salt=self.salt)
        except signing.BadSignature:
            return self.invalid()

        self.user = get_object_or_404(get_user_model(), pk=pk)
        return super(Reset, self).dispatch(request, *args, **kwargs)

    def invalid(self):
        return self.render_to_response(self.get_context_data(invalid=True))

    def get_form_kwargs(self):
        kwargs = super(Reset, self).get_form_kwargs()
        kwargs['user'] = self.user
        return kwargs

    def get_context_data(self, **kwargs):
        ctx = super(Reset, self).get_context_data(**kwargs)
        if 'invalid' not in ctx:
            ctx.update({
                'username': get_username(self.user),
                'token': self.kwargs['token'],
            })
        return ctx

    def form_valid(self, form):
        form.save()
        user_recovers_password.send(
            sender=get_user_model(),
            user=form.user,
            request=self.request
        )
        return redirect(self.get_success_url())
reset = Reset.as_view()


class ResetDone(generic.TemplateView):
    template_name = 'password_forgot/recovery_done.html'


reset_done = ResetDone.as_view()

我是django和stackoverflow的新手,请告诉我是否需要发布更多信息。

1 个答案:

答案 0 :(得分:0)

您的问题是成功网址没有命名空间

success_url_name = 'password_reset_sent'

但您在网址中使用了命名空间。

url(r'^password_forgot/', include('password_forgot.urls', namespace='password_forgot')),

您应该从网址中删除命名空间,

success_url_name = 'password_reset_sent'
url(r'^password_forgot/', include('password_forgot.urls')),

或者您可以尝试将名称空间添加到视图中:

success_url_name = 'password_forgot:password_reset_sent'
url(r'^password_forgot/', include('password_forgot.urls', namespace='password_forgot')),