Skip to main content

Overriding redirects in Django, to return where you came from

Project description

Provides the HTTP redirect flexibility of Django’s login view to the rest of your views.

Here’s what happens when you –as an anonymous user– try to access a view requiring you to log in:

  1. Django redirects you to /login?next=/page-you-wanted-to-see

  2. You log on

  3. Django’s login view notices the next parameter and redirects you to /page-you-wanted-to-see rather than /.

With Uturn, you’ll be able to use the same feature by simply changing some template code and adding middleware or decorators to your views.


Installation

django-uturn is available on Pypi:

pip install django-uturn

Uturn is currently tested against Django versions 1.4, 1.5 and 1.6 (including Python 3.2 and 3.3).

https://secure.travis-ci.org/roam/django-uturn.png?branch=master

Typical use cases

From master to detail and back again

You’ve got a list of… let’s say fish. All kinds of fish. To enable users to find fish by species, you’ve added a filter. Enter bass and your list is trimmed to only contain the Australian Bass, Black Sea Bass, Giant Sea Bass, Bumble Bass…

Wait a minute! Bumble Bass isn’t a species you’ve ever heard of - it’s probably the European Bass. So you hit the edit link of the Bumble Bass, change the name and save the form. Your view redirects you to the list. The unfiltered list. Aaargh!

If you’d just used the Uturn redirect tools, you would have been redirected to the filtered list. Much better (in most cases).

Multiple origins

This is basically a more general application of the previous use case. Suppose you have a form to create a new ticket that you can reach from both the project page and the ticket list page. When the user adds a new ticket, you want to make sure she’s redirected to the project page when she came from the project page and the ticket list page when she reached the form from the ticket list page.

Enter Uturn.

How to use Uturn

Redirecting in views

A typical form processing view function probably looks a bit like this:

from django.shortcuts import redirect, render
from forms import TicketForm

def add_ticket(request):
    if request.method == 'POST':
        form = TicketForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('ticket-list')
    else:
        form = TicketForm()
    context = {'form': form}
    return render(request, 'tickets/ticket_list.html', context)

This view always redirects to the ticket list page. Add Uturn redirects:

from django.shortcuts import render
from uturn.decorators import uturn
from forms import TicketForm

@uturn
def add_ticket(request):
    if request.method == 'POST':
        form = TicketForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('ticket-list')
    else:
        form = TicketForm()
    context = {'form': form}
    return render(request, 'tickets/ticket_list.html', context)

We simply add the uturn decorator to the view which will check the request for a valid next parameter and - if present - use that value as the target url for the redirect instead of the one you specified.

If you want to apply Uturn’s redirect logic to all requests, add the uturn.middleware.UturnMiddleware class to your middleware instead.

Passing the next page along

How do you add that next parameter to the URL in your project page? Here’s what you’d normally use:

<a href="{% url ticket-add %}">Add ticket</a>

This would render, depending on your url conf of course, a bit like this:

<a href="/tickets/add/">Add ticket</a>

Here’s what you’d use with Uturn:

{% load uturn %}
<a href="{% uturn ticket-add %}">Add ticket</a>

The uturn template tag will first determine the actual URL you want to link to, exactly like the default url template tag would. But the uturn tag will also add the current request path as the value for the next parameter:

<a href="/tickets/add/?next=%2Fprojects%2F">Add ticket</a>

Clicking this link on the project page and adding a ticket will get you redirected to the /projects/ URL if you add the correct field to your form.

Passing through forms

The easy way to add the parameter to your forms is by adding the uturn_param template tag inside your form tags. If you’re using Django’s builtin CSRF protection, you’ll already have something like this:

<form action="." method="post">
    {{ form.as_p }}
    {% csrf_token %}
    <input type="submit" value="Save">
</form>

Change that to this:

<form action="." method="post">
    {{ form.as_p }}
    {% csrf_token %}
    {% uturn_param %}
    <input type="submit" value="Save">
</form>

Don’t worry if you don’t want to use next as the parameter. You can specify a custom parameter name with the UTURN_REDIRECT_PARAM setting. And if you want to redirect to other domains, you can specify those domains with the UTURN_ALLOWED_HOSTS setting. Otherwise requests to redirect to other domains will be ignored.

Overriding URLs in templates

There’s just one more thing we need to change: the cancel link on your form:

<form action="." method="post">
    {{ form.as_p }}
    {% csrf_token %}{% uturn_param %}
    <input type="submit" value="Save"> or
    <a href="{% url ticket-list %}">cancel</a>
</form>

That link should point to the project page when applicable. Use the defaulturl tag to accomplish this:

{% load uturn %}
<form action="." method="post">
    {{ form.as_p }}
    {% csrf_token %}{% uturn_param %}
    <input type="submit" value="Save"> or
    <a href="{% defaulturl ticket-list %}">cancel</a>
</form>

The defaulturl tag will default to standard url tag behavior and use the next value when available. Here’s what your form would look like from the ticket list page (with or without the next parameter):

<form action="." method="post">
    ...
    <input type="submit" value="Save"> or
    <a href="/tickets/">cancel</a>
</form>

And here’s what that same form would look like when you reached it from the project page:

<form action="." method="post">
    ...
    <input type="submit" value="Save"> or
    <a href="/projects/">cancel</a>
</form>

Changelog

v0.3.0

Drop support for Django versions prior to 1.4 and verify support for Django 1.5 and 1.6.

v0.2.4

Make the uturn template tag work a bit more as expected.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-uturn-0.3.1.tar.gz (8.0 kB view details)

Uploaded Source

Built Distribution

django_uturn-0.3.1-py2.py3-none-any.whl (12.5 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file django-uturn-0.3.1.tar.gz.

File metadata

File hashes

Hashes for django-uturn-0.3.1.tar.gz
Algorithm Hash digest
SHA256 f9afd68fff52acb7b96061b5c82562f0d621ff9ad514b8bc1cf491cc3cd9cffb
MD5 bd3e3a73de34117f7f6649c01f5c5dfc
BLAKE2b-256 4160366673f3a2648062fc6dcafc9b38dd4c2006ed8fe46180a63228b77fa60e

See more details on using hashes here.

File details

Details for the file django_uturn-0.3.1-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for django_uturn-0.3.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 616d634d912528c57442c3d758058deae878c0f7b3cdb744f7608f3a46df1385
MD5 aa1c45350281aa9edbba261426067162
BLAKE2b-256 5cf42ec5a07e67276629994218d6e46036f222532bd8f368deb8037dcef93f2c

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page