Friday, September 13, 2013

Django - redirect

There're something I want to take note about using redirect in Django.

An error appears when I pass a view name as the redirect's parameter (myview of subapp1). Django cannot reverse it:

Reverse for 'myview' with arguments '()' and keyword arguments '{}' not found.


The thing is, I structured my Django project as nested apps:

myproject/
----------------mainapp/
------------------------------/subapp1
------------------------------/subapp2
------------------------------/subapp3

In the project's urlconf, I include the urlconf of subapps:

myproject/urls.py:

...
(r'^subapp1/', include('mainapp.subapp1.urls')),
...

and subapp1/urls.py:

...
url(r'^subapp1/myview/$', myview, name="my-view")
...

This complicated urlconf's structure make it impossible for Django to reverse the view if I don't explicit the path.

There're two way to resolve this issue:

1. Use the name of that view which is defined in the url mapping of the subapp:


subapp1/views.py:

...
return redirect('my-view')
...

2. Pass the full path of the view as the parameter of the redirect:

subapp1/views.py:

...
return redirect('mainapp.subapp1.views.myview')
...



These parts from Django's documation explain how to work with redirect:

redirect

redirect(to[, permanent=False], *args, **kwargs)
Returns an HttpResponseRedirect to the appropriate URL for the arguments passed.
The arguments could be:
  • A model: the model’s get_absolute_url() function will be called.
  • A view name, possibly with arguments: urlresolvers.reverse() will be used to reverse-resolve the name.
  • A URL, which will be used as-is for the redirect location.
By default issues a temporary redirect; pass permanent=True to issue a permanent redirect

Examples

You can use the redirect() function in a number of ways.
  1. By passing some object; that object’s get_absolute_url() method will be called to figure out the redirect URL:
    def my_view(request):
        ...
        object = MyModel.objects.get(...)
        return redirect(object)
    
  2. By passing the name of a view and optionally some positional or keyword arguments; the URL will be reverse resolved using the reverse() method:
    def my_view(request):
        ...
        return redirect('some-view-name', foo='bar')
    
  3. By passing a hardcoded URL to redirect to:
    def my_view(request):
        ...
        return redirect('/some/url/')
    
    This also works with full URLs:
    def my_view(request):
        ...
        return redirect('http://example.com/')
    
By default, redirect() returns a temporary redirect. All of the above forms accept a permanent argument; if set to True a permanent redirect will be returned:
def my_view(request):
    ...
    object = MyModel.objects.get(...)
    return redirect(object, permanent=True)


References: https://docs.djangoproject.com/en/1.4/topics/http/shortcuts/