我试图在我的项目(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的新手,请告诉我是否需要发布更多信息。
答案 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')),