How to debug Django NoReverseMatch errors? - django

Folks, I am getting a NoReverseMatch error for a particular url call.
I'd like to know: are there any good tools to debug these in general? For example, some way to list out which URLs are registered?
My particular example:
Template:
<a href=
"{% url django.contrib.auth.views.redirect_to_login blarg %}">log in</a>
Error:
NoReverseMatch: Reverse for
'settings.django.contrib.auth.views.redirect_to_login'
with arguments '('[[ UNDEFINED VARIABLE ]]',)'
and keyword arguments '{}' not found.
I am using Google App Engine with appenginepatch, so Django itself is modified.

In this particular case where the url reversal uses the full path to the view function, the easy thing to do is just go look at the view function. In Django-1.1 this looks like:
def redirect_to_login(next, login_url=None,
redirect_field_name=REDIRECT_FIELD_NAME):
"Redirects the user to the login page, passing the given 'next' page"
if not login_url:
login_url = settings.LOGIN_URL
return HttpResponseRedirect('%s?%s=%s' % (login_url,
urlquote(redirect_field_name),
urlquote(next)))
This function does not even take a request object, so its really not even a proper view, and it is not even registered in django/contrib/auth/urls.py. That means it's probably only meant to be used as a helper function in other views.
In any case, based on your particular example, what you probably wanted to do was use the plain old login url like so:
<a href="{% url django.contrib.auth.views.login %}?next={{request.path}}">
log in
</a>
Also, I believe if you set TEMPLATE_DEBUG = True in your settings, you will get a list of all the url patterns django checked against before throwing the error.

Related

In django-rest-auth, the password reset confirm URL doesn't work--is it missing arguments?

If you look at urlpatterns in django.contrib.auth.urls, the password_reset_confirm URL takes uidb64 and token params, which makes sense--when clicked on, this will identify the user resetting the password. However, django-rest-auth's rest_password_reset_confirm URL doesn't take any arguments: it just goes to password/reset/confirm/. How can it work? I get the following 500 error when submitting my email to reset my password, and I'm not surprised--the error makes sense:
NoReverseMatch: Reverse for 'password_reset_confirm' with arguments '()' and keyword arguments '{u'uidb64': 'NA', u'token': u'4lj-65cd7b4219c9206126b4'}' not found.
What I don't understand is it seems like such a basic thing that I must be doing something wrong--otherwise everyone using django-rest-auth would get this error because the arguments are clearly missing in the URL definition. Has anyone else experienced it and if so, did you update the URL to fix it?
UPDATE: It looks like django-rest-auth, by default, simply uses native Django's contrib/admin/templates/registration/password_reset_email.html template.
Turns out there's a simple one-line fix--add this to your base url patterns:
url(r'^', include('django.contrib.auth.urls')),
I have used following once in my template:
{% url 'django.contrib.auth.views.password_reset_confirm' uidb64=uid token=token %}
And, it works fine. Can you please show your template include structure?

LOGIN_REDIRECT_URL in django

I am very new to Django and I'm nearing the end of the django girls tutorial. I have added "#login_required" above my post_detail in views (view for clicking on a specific post) and added a login.html template. So when I click on a post title I get redirected to my login page (so far, so good) and the url is: http://127.0.0.1:8000/accounts/login/?next=/post/11/ (trying this on my computer atm.)
Then I type in my admin name/password and automatically get redirected to http://127.0.0.1:8000/accounts/profile/ and of course get a "Page not found (404)" (since I have no url/view/template for that). I thought "Dang, I just wanted to be redirected to /post/11/"!
Looked around on stack overflow and found this question:
Signing in leads to "/accounts/profile/" in Django (sounds about right)
and got the answer
Change the value of LOGIN_REDIRECT_URL in your settings.py.
So I looked up LOGIN_REDIRECT_URL in the Django documentation:
Default: '/accounts/profile/'
The URL where requests are redirected after login when the contrib.auth.login view gets no next parameter.
This is used by the login_required() decorator, for example.
This setting also accepts named URL patterns which can be used to reduce configuration duplication since you don’t have to define the URL in two places (settings and URLconf).
Deprecated since version 1.8: The setting may also be a dotted Python path to a view function. Support for this will be removed in Django 1.10.
But doesn't my contrib.auth.login get a next parameter? (looking at my url that say "?next=/post/11/" at the end) Please help me out here, I'm lost for what the problem could be here :(
You can view the page at:
http://finbel.pythonanywhere.com/
And the source code at:
https://github.com/Finbel/my-first-blog
UPDATE (1):
So I now know that the LOGIN_REDIRECT_URL is the thing that's deciding where I end up next, which must mean that it ignores the next-parameter in the url. I googled further on the problem and found this question which was very similar to my problem, i.e.
Documentation states that I need to use the "next" parameter and context processors. I have the {{next}} in my template, but I'm confused on how to actually pass the "/gallery/(username)". Any help would be greatly appreciated.
(I don't even have the {{next}} in my template, where/how should I add it?)
The preferred answer to that question seemed to be:
Django's login view django.contrib.auth.views.login accepts a dictionary named extra_context. The values in the dictionary are directly passed to the template. So you can use that to set the next parameter. Once that is done, you can set a hidden field with name next and value {{ next }} so that it gets rendered in the template.
But I'm not sure how to interpret this. While writing this edit I got an answer on this post (by kacperd) and will read it through now)
The problem is that contrib.auth.login doesn't get the next parameter.
When you try to get the login_required view without credentials your request is redirect to login view, and the template you created is rendered. The next parameter is present in this view, but when you perform the login action which is submitting the form, you are not including next in your request so contrib.auth.login doesn't get it and redirects to default page.
The solution to your problem is to include the next param and pass it forward. You can do this by modifying your login template. Simply add ?next={{ request.GET.next }} to form action attribute.
<form method="post" action="{% url 'django.contrib.auth.views.login' %}?next={{ request.GET.next }}">

Django: How to return to previous URL

Novice here who learned to develop a web app with python using Flask. Now I'm trying to learn django 1.9 by redoing the same app with django.
Right now I am stuck at trying to get the current URL and pass it as an argument so that the user can come back once the action on the next page is completed.
In Flask, to return to a previous URL, I would use the 'next' parameter and the request.url to get the current url before changing page.
In the template you would find something like this:
Buy punchcard :
and in the view:
redirect(request.args.get("next"))
I thought it would be about the same with django, but I cannot make it work. I did find some suggestions, but they are for older django version(older than 1.5) and do not work anymore(and they are pretty convulsed as solutions goes!)
Right now, in my view I am using
return redirect(next)
Note: The use of return redirect in django seems very recent itself if I judge by solutions on the web that always seem to use return HttpResponse(..., so I take it alot of changes happened lately in how to do things.
and in the template I have
<a href="{% url 'main:buy_punchcard' member.id next={{ request.path }} %}">Buy punchcard</p>
but this actually return an error
Could not parse the remainder: '{{' from '{{'
I did add the context_processors in settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
)
But this is only the last error in a very long streak of errors. Bottom line is, I can't make it work.
As such, anyone could point me in the right direction as to what is the way to do this in django 1.9? It look like a pretty basic function so I thought it would be easier somehow.
If you want next to be included in the query string, then move it outside of the url tag:
<a href="{% url 'main:buy_punchcard' member.id %}?next={{ request.path }}">Buy punchcard</p>
In your view, you can fetch next from request.GET, and return the redirect response using either HttpResponseRedirect or the redirect shortcut.
from django.utils.http import is_safe_url
next = request.GET.get('next', '/default/url/')
# check that next is safe
if not is_safe_url(next):
next = '/default/url/'
return redirect(next)
Note that it might not be safe to redirect to a url fetched from the query string. For example, it could link to a different domain. Django has a method is_safe_url that it uses to check next urls when logging in or out.
You don't need {{ }} there, just:
<a href="{% url 'main:buy_punchcard' member.id next=request.path %}">Buy punchcard</p>

Django: How do I pass request URLs through urls.py?

I have a django app with the following entries related to logging out in urls.py:
(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page':'/logout_page/'}),
(r'^logout_page/$', 'django.views.generic.simple.direct_to_template', {'template':'registration/logged_out.html'}),
I want to add a "Log back in" link in logged_out.html, which requires me to know the location (URL) from where the user originally logged out.
How do I reference that URL in the logout dispatcher entry, and how do I pass it to the logout_page entry?
Thanks in advance
I do not exactly understand what you mean by "passing variables here" but you can pass variables to the views from urls like this
r'^(category/page/(?P[0-9]+)/$
page_number is passed as a variable to the url
But what I think you are looking for is to pass the previous prefer which you should be able access in the template like this :
{{ request.META.HTTP_REFERER }}
So you can do something like :
Login
in the template of logout_page to achieve what you are looking for

django 'url' template tag error

My URLconf contains this pattern:
url(r'^accounts/logout/$','django.contrib.auth.views.logout', name="logout"),
And I've trying to reverse that in a template with the URL tag like this:
logout
But I keep getting the following error:
Reverse for 'logout' with arguments '()' and keyword arguments '{'next_page': u'/first-page/child/'}' not found
I thought django.contrib.auth.views.logout is supposed to take an option next_page parameter. I'm sure I'm missing something obvious, but I'm not sure what it is.
Yes you're right, django.contrib.auth.views.logout does accept an optional "next_page" parameter, but don't forget that the "url" tag matches to urlconf patterns, not views, so it's not aware of what is or isn't a parameter of a view. So this suggests that you need to make "next_page" a named group in the regexp for the above pattern, which you could do, but there's an easier way to handle redirects...
Looking at django.contrib.auth.views.logout, you can see that in the absence of a "next_page" parameter, the view redirects to whatever url is provided in either request.GET or request.POST with the key "redirect_field_name", a parameter which defaults to "REDIRECT_FIELD_NAME" which in turn defaults to the string "next". So leaving your urlconf the way it is, you can do something like this in your template:
<a href='{% url logout %}?next={{ request.path }}'>logout</a>
Basically Django's URL dispatcher is looking at the urlconf and that argument and saying "I don't know where to put this argument" because it doesn't look at the view functions the urls point to, only the urlconf and the patterns in it.
Right now there's no place in your url pattern for that argument.
i.e. you can call django.contrib.auth.views.logout with the extra arguments if you write your own pattern for it or if you call it from your own view, but not from its default url pattern.
One of these url patterns might work for you (not tested):
url(r'^accounts/logout/(?P<next_page>.*)?$','django.contrib.auth.views.logout', name="logout"),
url(r'^accounts/logout/$','django.contrib.auth.views.logout', kwargs={'next_page':None}, name="logout"),
Hope that helps!