我注意到Django处理我的url模式的一个奇怪的行为。用户应该登录,然后重定向到他们的个人资料页面。我还可以让用户编辑他们的个人资料。
以下是我的某个应用的网址格式:
urlpatterns=patterns('student.views',
(r'profile/$', login_required(profile,'student')),
(r'editprofile/$', login_required(editprofile,'student')),
)
这适用于名为student的应用。如果用户转到/ student / profile,他们应该获取配置文件视图。如果他们转到/ student / editprofile,他们应该获得editprofile视图。我设置了一个名为login_required的函数,它对用户进行了一些检查。这比我只能用注释处理的要复杂一点。
这是login_required:
def login_required(view,user_type='common'):
print 'Going to '+str(view)
def new_view(request,*args,**kwargs):
if(user_type == 'common'):
perm = ''
else:
perm = user_type+'.is_'+user_type
if not request.user.is_authenticated():
messages.error(request,'You must be logged in. Please log in.')
return HttpResponseRedirect('/')
elif request.user.is_authenticated() and user_type != 'common' and not request.user.has_perm(perm):
messages.error(request,'You must be an '+user_type+' to visit this page. Please log in.')
return HttpResponseRedirect('/')
return view(request,*args,**kwargs)
return new_view
无论如何,奇怪的是,当我访问/ student / profile时,即使我到了正确的页面,login_required也会打印出以下内容:
Going to <function profile at 0x03015DF0>
Going to <function editprofile at 0x03015BB0>
为什么同时打印?为什么要试图访问这两个?
即使更奇怪,当我尝试访问/ student / editprofile时,个人资料页面会加载,这就是打印的内容:
Going to <function profile at 0x02FCA370>
Going to <function editprofile at 0x02FCA3F0>
Going to <function view_profile at 0x02FCA4F0>
view_profile是一个完全不同的应用程序中的函数。
答案 0 :(得分:2)
这两种模式:
(r'profile/$', login_required(profile,'student')),
(r'editprofile/$', login_required(editprofile,'student')),
两者都匹配http://your-site/student/editprofile
。
尝试:
(r'^profile/$', login_required(profile,'student')),
(r'^editprofile/$', login_required(editprofile,'student')),
Django首先使用视图匹配模式(see number 3 here)。
答案 1 :(得分:2)
不确定为什么你不能使用标准的@login_required装饰器 - 看来你的版本实际上提供了 less 功能,因为它总是重定向到\
,而不是实际登录视图。
在任何情况下,打印两者的原因是因为print
语句位于装饰器的顶层,因此在urlconf 评估时执行。如果将它放在内部new_view
函数中,它只会在实际调用时执行,并且只应打印相关的视图名称。
答案 2 :(得分:1)
你的login_required
看起来像是一个蟒蛇装饰者。您需要在urls.py中使用它的任何原因吗?
我认为在读取print 'Going to '+str(view)
时评估urlpatterns
行以确定要执行的视图。它看起来很奇怪,但我认为它不会伤害你。
每次点击视图时都不会执行行print 'Going to '+str(view)
,只有在评估了网址模式时(我认为)。 new_view
中的代码是唯一将作为视图的一部分执行的代码。