Django URL reversing NoReverseMatch issue - regex

I'm trying to use reverse to redirect a user to a login page from a third party App I'm using.
The URL config has:
urlpatterns = [
# authentication / association
url(r'^login/(?P<backend>[^/]+){0}$'.format(extra), views.auth,
name='begin'),
How can I accomplish this? I've tried
return redirect(reverse('social:login'), args=('facebook',))
and
return redirect(reverse('social:login'), kwargs={'backend':fb})
(to get to /login/facebook) but I'm getting a NoReverseMatch
The Django URL system and RegExes are confusing me a bit =(
EDIT: All right, it looks like I was making a mess with these URLs.
A simple solution that works (thank you #Alasdair in the comments):
return redirect('social:begin', backend='facebook')

Related

Django Tastypie ToManyField not properly resolving related URIs

I've got a Django backend that is using Tastypie to generate its RESTful API. The endpoint of this API does not sit at the top-level of the domain; rather, it exists in a "subfolder" location through the use of WSGIScriptAlias. Most, of the time, this works fine. But I've discovered that when one of my resources has a ToManyField relationship, Tastypie throws an error. Here is some of my relevant code. The WSGIScriptAlias line:
WSGIScriptAlias /english/rubric /var/webapps/django/rubric/apache/django.wsgi
Snippet from the resource that has problems:
class TraitResource(ModelResource):
criteria = fields.ToManyField('rubric.rubric.api.CriterionResource', "criteria", related_name='trait', full = True)
class Meta:
queryset = Trait.objects.all()
authentication=SessionAuthentication()
list_allowed_methods=['get']
always_return_data=True
class CriterionResource(ModelResource):
class Meta:
queryset = Criterion.objects.all()
authentication=SessionAuthentication()
list_allowed_methods=['get']
always_return_data=True
My urls.py:
v1_api = Api(api_name='v1')
v1_api.register(TraitResource())
v1_api.register(CriterionResource())
urlpatterns = patterns('',
(r'^login/$', 'django_cas.views.login'),
(r'^logout/$', 'django_cas.views.logout'),
(r'^api/', include(v1_api.urls))
)
Snippet from the error message:
{
error_message: "{'path': u'english/rubric/api/v1/rubric', 'tried': [[<RegexURLPattern None ^login/$>], [<RegexURLPattern None ^logout/$>], [<RegexURLResolver [<RegexURLPattern api_v1_top_level ^(?P<api_name>v1)/?$>, <RegexURLResolver [<RegexURLPattern api_dispatch_list ...
(it goes on from there to list all of the URLs it has tried and failed to find a match for).
So if I understand correctly, what is happening is that, because of my WSGIScriptAlias, the related objects are reporting their full path as the resource URI, but then when tastypie goes to get the related objects to return with the one I've called, they aren't matching anything in urls.py (because it only needs the url patterns relative to the WSGI app mount point). I've verified this is the case by temporarily modifying the WSGIScriptAlias so the API sits at the root -- and then it all works fine. So what do I need to do in order to keep it with the subfolder URL pattern? I've played around a bit with both overriding prepend_urls and get_resource_uri, but am not really getting how those functions are used in a resource class and so I'm not sure if that's the right strategy for me. Thanks in advance.
What version of tasyypie are you using?
I had the same problem, seems to be solved by upgrading fro 0.9.12 to 0.9.15.

Right way to handle HttpResponseRedirect

I have a Django app I'm trying to deploy. The Apache setting is configured in the way that i access my wsgi app by the following URL:
sitename.com/~amartino
Meaning I have only a wsgi.py file in my public_html directory.
I access my Django site via URL:
sitename.com/~amartino/expofit
For that's the way its been set in urls.py.
urlpatterns = patterns('',
('/param_select/$',session_check(param_select)),
('registration/$',registration),
('result_show/(\d+)',session_check(result_show)),
('^expofit/$',media_clean(start)),
('result_pick/$',session_check(result_pick)),
('mail_report/$',session_check(mail_report)),
('notification/$',session_check(notification)),
However, the problem I'm getting (which didn't show up in development :) ) is that I'm using a hardcoded HttpResponseRedirect in views.py.
...
#If all fields are valid
return HttpResponseRedirect('/expofit/param_select/')
#else reload page
...
Since the production environment doesn't place my site in the root of the URL, i'm having errors now because the upper HttpResponseRedirect translates to
sitename.com/expofit/param_select/
which isn't recognized by Apache.
I suppose I could remove the slash and have:
return HttpResponseRedirect('expofit/param_select/')
which would result in:
sitename.com/~amartino/expofit/registration/expofit/param_select/
but that doesn't seem the right way to do it for I would end up with a huge URL in no time.
Where is the design/configuration flaw here?
"the problem I'm getting that I'm using a hardcoded HttpResponseRedirect"
Well, don't do that then. That's why Django provides the reverse function, which takes your url name and calculates the proper absolute URL.

Django: Permanent redirect of URL with regex parameters

I've been looking all over and can't find what I'm looking for.
I've found a way to redirect urls without parameters and keywords - but how to do it with parameters?
I want to redirect this:
(r'^andelsboligforeninger/(?P<page>[\d]*?)/$', 'cooperatives'),
to this:
(r'^liste-over-andelsboligforeninger/(?P<page>[\d]*?)/$', 'cooperatives'),
It should be a permanent redirect. This will be good for the SEO, and I get so many debug mails because of googlebot.
It seems I've found my answer in the django docs - I didn't look hard enought after all!
https://docs.djangoproject.com/en/1.1/ref/generic-views/
urlpatterns = patterns('django.views.generic.simple',
('^foo/(?P<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}),
)
First of all you need to do some changes in the url. Use url function and then give a name to the url. You have some issues in your url, for example you have used ?P but did'nt give a name to the capturing group. Second [\d]*? there is no need for ? because * means there can be a digit or not at all. So after considering all the above mentioned bugs and techniques in the end your url should look like this:
url(r'^liste-over-andelsboligforeninger/(?P<cooperative_id>\d*)/$', 'cooperatives', name="cooperatives")
Then in the view you can use reverse url resolution as:
redirect(reverse('cooperatives', kwargs={'cooperative_id': some_id}))

Why doesn't this django code work?

urls.py
url(r'^some/page/$', views.some_page,
{'template_name': 'some/page.html'},
name='some_page'),
views.py
url = request.build_absolute_uri(reverse('some_page')).lower()
response = HttpResponseRedirect(url)
return response
Question:
Why doesn't this code work?
url = request.build_absolute_uri(reverse('some_page',
kwargs={"template_name": "another/page.html"})).lower()
I'm using django 1.2 on google appengine. Since I get the same error for any kind of typo/mistake, I didn't think it was useful to paste that error message here.
Thanks.
Because reverse expects the arguments to “fill in” regular expressions in the url. So reverse('some_page') should work.
What do you expect it to do?

Reverse Not Found: Sending Request Context in from templates

N.B This question has been significantly edited before the first answer was given.
Hi,
I'm fairly new to django, so apologies if I'm missing something obvious.
I've got a urls.py file that looks like this:
urlpatterns = patterns(
'',
(r'^$', 'faros.lantern.views.home_page'),
(r'^login/$', 'django.contrib.auth.views.login'),
(r'^logout/$', 'django.contrib.auth.views.logout'),
(r'^about/$', 'faros.lantern.views.about_page_index', {}, 'about_page_index'),
(r'^about/(?P<page_id>([a-z0-9]+/)?)$', 'faros.lantern.views.about_page', {}, 'about_page'),
)
Views that looks like this:
def about_page_index(request):
try:
return render_to_response('lantern/about/index.html', context_instance=RequestContext(request))
except TemplateDoesNotExist:
raise Http404
def about_page(request, page_id):
page_id = page_id.strip('/ ')
try:
return render_to_response('lantern/about/' + page_id + '.html', context_instance=RequestContext(request))
except TemplateDoesNotExist:
raise Http404
And a template that includes this:
Contact
Contact
I'm getting this error message:
Caught an exception while rendering: Reverse for '<function about_page at 0x015EE730>' with arguments '()' and keyword arguments '{'page_id': u'contact'}' not found. The first reverse works fine (about_page_index), generating the correct URL without error messages.
I think this is because the request argument to the about_page view (request) is used, so I need to pass it in when I generate the URL in my template. Problem is, I don't know how to get to it, and searching around isn't getting me anywhere. Any ideas?
Thanks,
Dom
p.s. As an aside, does that method of handling static "about" type pages in an app look horrific or reasonable? I'm essentially taking URLs and assuming the path to the template is whatever comes after the about/ bit. This means I can make the static pages look like part of the app, so the user can jump into the about section and then right back to where they came from. Comments/Feedback on whether this is djangoic or stupid appreciated!
If I guess correctly from the signature of your view function (def about_page(request, page_id = None):), you likely have another URL configuration that points to the same view but that does not take a page_id parameter. If so, the django reverse function will see only one of these, and it's probably seeing the one without the named page_id regex pattern. This is a pretty common gotcha with reverse! :-)
To get around this, assign a name to each of the url patterns (see Syntax of the urlpatterns variable). In the case of your example, you'd do:
(r'^about/(?P<page_id>([a-z]+/)?)$', 'faros.lantern.views.about_page',
{}, 'about_with_page_id')
and then in the template:
Contact
Edit
Thanks for posting the updated urls.py. In the url template tag, using the unqualified pattern name should do the trick (note that I'm deleting the lantern.views part:
Contact
Contact
Edit2
I'm sorry I didn't twig to this earlier. Your pattern is expressed in a way that django can't reverse, and this is what causes the mismatch. Instead of:
r'^about/(?P<page_id>([a-z]+/)?)$'
use:
r'^about/(?P<page_id>[a-z0-9]+)/$'
I created a dummy project on my system that matched yours, reproduced the error, and inserted this correction to success. If this doesn't solve your problem, I'm going to eat my hat! :-)