登录后尝试将用户名添加到 url 时收到 NoReverseMatch 错误
Posted
技术标签:
【中文标题】登录后尝试将用户名添加到 url 时收到 NoReverseMatch 错误【英文标题】:Receiving a NoReverseMatch error while trying to add the username to the url after login 【发布时间】:2017-05-28 06:17:50 【问题描述】:当用户点击“登录”时,我希望他们登录并重定向到即 www.exampledomain.com/accounts/usernameGoesHere/
这是我的***网址:
from django.conf.urls import url, include
from django.contrib import admin
# Namespace URLs
app_name = "pto_request"
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^accounts/', include('accounts.urls')),
]
这里是帐户的网址:
from django.conf.urls import url
from django.contrib.auth.decorators import login_required
from accounts.views import (login_view, register_view, logout_view)
from . import views
app_name = 'accounts'
urlpatterns = [
# root url will look like www.website.com/accounts/
url(r'^login/$', login_view, name='login'),
url(r'^logout/$', logout_view, name='logout'),
url(r'^register/$', register_view, name='register'),
url(r'^(?P<username>[0-9a-zA-Z._]+)/$', login_required(views.IndexView.as_view()), name = 'index'),
]
这是我的登录视图:
def login_view(request):
title = "Login"
user_form = UserLoginForm(request.POST or None)
if user_form.is_valid():
username = user_form.cleaned_data.get('username')
password = user_form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
login(request, user)
return redirect(reverse('accounts:index', args=[username]))
return render(request, 'form.html', 'user_form':user_form, 'title':title)
最后这是我收到的错误的回溯日志:
Environment:
Request Method: GET
Request URL: http://localhost:8000/accounts/FlashBanistan/
Django Version: 1.10.5
Python Version: 3.5.2
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'datetimewidget',
'accounts']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware']
Template error:
In template C:\django projects\PTO\accounts\templates\accounts\index.html, error at line 0
Reverse for 'index' with arguments '()' and keyword arguments '' not found. 1 pattern(s) tried: ['accounts/(?P<username>[0-9a-zA-Z._]+)/$'] 1 : % extends 'base.html' %
2 : % load crispy_forms_tags %
3 :
4 : % block content %
5 :
6 : form.media
7 :
8 :
9 : <div class="container">
10 : <div id="calendar">
Traceback:
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\exception.py" in inner
39. response = get_response(request)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py" in _get_response
217. response = self.process_exception_by_middleware(e, request)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py" in _get_response
215. response = response.render()
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\response.py" in render
109. self.content = self.rendered_content
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\response.py" in rendered_content
86. content = template.render(context, self._request)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\backends\django.py" in render
66. return self.template.render(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py" in render
208. return self._render(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py" in _render
199. return self.nodelist.render(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py" in render
994. bit = node.render_annotated(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py" in render_annotated
961. return self.render(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\loader_tags.py" in render
174. return compiled_parent._render(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py" in _render
199. return self.nodelist.render(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py" in render
994. bit = node.render_annotated(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py" in render_annotated
961. return self.render(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\defaulttags.py" in render
315. return nodelist.render(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py" in render
994. bit = node.render_annotated(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py" in render_annotated
961. return self.render(context)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\defaulttags.py" in render
439. url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\urls\base.py" in reverse
91. return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
File "C:\Users\achesley\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\urls\resolvers.py" in _reverse_with_prefix
392. (lookup_view_s, args, kwargs, len(patterns), patterns)
Exception Type: NoReverseMatch at /accounts/FlashBanistan/
Exception Value: Reverse for 'index' with arguments '()' and keyword arguments '' not found. 1 pattern(s) tried: ['accounts/(?P<username>[0-9a-zA-Z._]+)/$']
【问题讨论】:
你不能从 login_view 'redirect()' 他们吗? 为什么你不能从 login_view 'return redirect("accounts/%s" % username)'? 你的代码看起来不安全,顺便说一句;在您执行 login() 时,用户可能是 None。 像稳定一样安全还是像安全一样安全?我不能只返回您输入的内容,因为我的网址未设置为接受字符串。 为什么还要附加用户名。在随后的帐户视图中,您不能从request.user
获得该信息吗?
【参考方案1】:
第 1 步。将您的 index
网址移到最后,并给它一个仅接受用户名的模式。将index
url 移到最后很重要,否则它将覆盖同一 urls 文件中的所有其他 url,例如,login
、logout
。
app_name = 'accounts'
urlpatterns = patterns(
'',
url(r'^login/', login_view, name='login'),
url(r'^logout/', logout_view, name='logout'),
url(r'^register/', register_view, name='register'),
#
# +------------ this url should come at last !!!!
# |
# v
url(r'^(?P<username>[0-9a-zA-Z._]+)/$', login_required(views.IndexView.as_view()), name = 'index'), name = 'index'),
)
第 2 步。redirect
使用登录用户名发送到您的 index
网址。
return redirect(reverse('accounts:index', args=(username, )))
EDIT 2 修复模板错误
根据您的堆栈跟踪,您的模板中发生了错误,django 无法反转index
的网址。检查模板中的代码后,我发现,您调用了一个以accounts:index
为参数的url
函数,但没有在方法调用中指定用户名kwarg。
所以你可以用下面的代码修复错误:
% if user %
<li><a href="% url 'accounts:index' user.username %"><span class="glyphicon glyphicon-user"></span> user.username </a></li>
% endif %
【讨论】:
哇,我不知道我需要多长时间才能找到这个错误。我会在早上进行更多研究,但是错误堆栈中是否有任何东西可以将我指向这个方向?我想学习如何更好地解析错误。 我专注于堆栈跟踪......它说模板错误......所以它一定是在你的模板中使用错误的 url.. 所以最后我得到了这个缺陷...... 如果您想编辑您发布的答案以反映您的发现,我会接受它作为答案。【参考方案2】:另一种方法是将用户名作为查询字符串添加到重定向函数中。这样您就不必更改您的网址:
return redirect("/accounts/?username=%s" % user.username)
此外,您可以在视图中从request.user
获取用户(无需将其添加到 url),这是我推荐的——除非出于审美目的,您希望在 url 中使用它。
这是另一个登录功能供参考,它修复了您问题的 cmets 中讨论的一些问题:
def login(request):
username = request.POST.get('username')
password = request.POST.get('password')
if username and password:
# Make sure its an active user, or else return an error message.
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
auth_login(request, user)
next = request.session.get('next', 'root')
return redirect(next)
else:
messages.warning(request, "Invalid username / password.")
return render(request, 'login.html')
【讨论】:
【参考方案3】:Django 的 url 接受模式,也就是说,您可以为主页设置一个 url,例如:
url(r'^(?P<username>[a-zA-Z]*)$', views.userhome, name = 'index'),
在您的用户的索引视图中,您将从 url 获得一个变量,因此函数(与基于类的视图相同)将如下所示:
def userhome(request, username):
要使用这个url,你可以使用reverse
函数:
#after login...
return redirect(revers('index', args=[username]))
这里有一些有用的提示:
-
最好在您的views.py 中编写您的装饰器,因为在您的urls.py 中编写会使它过于混乱。
尝试使用reverse function 用户获取网址,而不是直接在代码中编写
关于reverse和url config的更多信息,您可以参考Django's doc。
【讨论】:
以上是关于登录后尝试将用户名添加到 url 时收到 NoReverseMatch 错误的主要内容,如果未能解决你的问题,请参考以下文章