Reputation: 8296
I've noticed a strange behavior with how Django is processing my url patterns. A user should login and then be redirected to their profile page. I also have the ability for a user to edit their profile.
Here are my URL patterns for one of my apps:
urlpatterns=patterns('student.views',
(r'profile/$', login_required(profile,'student')),
(r'editprofile/$', login_required(editprofile,'student')),
)
This is for an app called student. If the user goes to /student/profile they should get the profile view. If they go to /student/editprofile they should get the editprofile view. I setup a function called login_required which does some checks on the user. It's a little more complicated than I could handle with just annotations.
Here's 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
Anyways, the weird thing is that, when I visit /student/profile, even though I get to the right page, login_required prints the following:
Going to <function profile at 0x03015DF0>
Going to <function editprofile at 0x03015BB0>
Why is it printing both? Why is it trying to visit both?
Even weirder, when I try to visit /student/editprofile, the profile page is what loads and this is what's printed:
Going to <function profile at 0x02FCA370>
Going to <function editprofile at 0x02FCA3F0>
Going to <function view_profile at 0x02FCA4F0>
view_profile is a function in a completely different app.
Upvotes: 3
Views: 339
Reputation: 599926
Not sure why you can't use the standard @login_required decorator - it seems that your version actually provides less functionality, given that it always redirects to \
, rather than the actual login view.
In any case, the reason why both are printed is because the print
statement is in the top level of the decorator, and thus is executed when the urlconf is evaluated. If you put it in the inner new_view
function, it will only be executed when it is actually called, and should print only the relevant view name.
Upvotes: 2
Reputation: 46453
These two patterns:
(r'profile/$', login_required(profile,'student')),
(r'editprofile/$', login_required(editprofile,'student')),
Both match http://your-site/student/editprofile
.
Try:
(r'^profile/$', login_required(profile,'student')),
(r'^editprofile/$', login_required(editprofile,'student')),
Django uses the view who's pattern matches first (see number 3 here).
Upvotes: 2
Reputation: 2977
Your login_required
looks like it's a python decorator. Any reason you need to have it in your urls.py?
I think the print 'Going to '+str(view)
line is getting evaluated when urlpatterns
is read to determine which view to execute. It looks weird, but I don't think it'll hurt you.
The line print 'Going to '+str(view)
will not be executed every time the view is hit, only when the url pattern is evaluated (I think). The code in new_view
is the only code that will execute for certain as part of the view.
Upvotes: 1