djangourlhttp-redirectdjango-context

How do I set the "next" context variable in Django so I can redirect my user to the appropriate page?


I'm aware that there is a context variable called "next" which allows you to specify the URL to redirect to after a page, which is commonly used when you want to redirect a user to a login page, then redirect them back to the page they were at before the login page once they've logged in.

In my views I've resorted to manually setting it via the URL such as redirecting to /login/?next=/someurl, but this isn't a clean way. I've tried googling and such, but there is surprisingly little information about it online.

How exactly do you set the context variable "next"? My site has a form that anyone can see, but only logged in users can submit. Right now if the user isn't logged in, they will get redirected to the login page with the "?next=/someurl/" attached to it so they get sent back to the original form once they log in.

However, from the login page there is a link to the sign up page for users who don't have an account, and I want to set "next" to be the original form page so that after they sign up they are redirected back to the original form. Any ideas or advice?


Solution

  • It sounds like you want to not simply use next for one redirect, but persist it across two redirects: Some form page -> login -> signup -> Get back to some form

    For the login page by itself, Django provides some automatic help for this (if you use the built-in auth views). But the second hop to the signup page requires some custom code explained below.

    If you are using Django's built-in login view, and have created your own template for it, then Django will pass the current value of next to the template as a context variable called (appropriately) next. You can use that in the link to your sign-up page like this:

    <a href="{% url 'your_signup_page' %}{% if next %}?next={{ next }}{% endif %}">Sign me up!</a>
    

    Consequently, in the view you create to handle your user signup page, the value of next will be accessible as a GET param:

    def signup(request):
        if request.method == 'GET':
            next = request.GET.get('next', None)
            if next:
                # Add it as a hidden input in your signup form
                # Or re-append it as a GET param
                # Or stick it in the user's session, which is
                # what this example does:
                request.session['next'] = next
    

    Finally, in the same signup view, when you respond to the POSTed signup form, retrieve the next value in whichever way you chose to propogate it in the GET request, and redirect to it's value.

    def signup(request):
        ....
        # POST handling section
        if signup_form.is_valid():
            next = request.session.get('next', None)
            if next:
                # See caution note below!
                return redirect(next)
    

    Caution:

    Be aware that you should check and sanitize the next value before you redirect to it after processing the signup form, to prevent browser-side tampering. For example, it's common to validate that the URL belongs to your own domain (if that's appropriate) and/or that Django's resolve function is able to successfully resolve it.