Oleg
Oleg

Reputation: 847

How to redirect to previous page in Django after POST request

I face a problem which I can't find a solution for. I have a button in navbar which is available on all pages and it is a button responsible for creating some content.

View that links with button:

def createadv(request):
    uw = getuw(request.user.username)
    if request.method =='POST':
    form = AdverForm(request.POST, request.FILES)
    if form.is_valid():
        form.instance.user = request.user
        form.save()
        return HttpResponseRedirect('/', {'username': request.user.username, 'uw': uw})
    args = {}
    args.update(csrf(request))
    args['username'] = request.user.username
    args['form'] = AdverForm()
    args['uw'] = uw
    return  render_to_response('createadv.html', args)

If you can see now I always redirect to main page '/' after creating content but I want to go back to the page with which I launched the creation of content.

Upvotes: 77

Views: 96248

Answers (7)

Deskom88
Deskom88

Reputation: 59

Use HTTP_REFERER value:

  1. for use in func return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))

  2. for use in template <a href="{{request.META.HTTP_REFERER}}">Go Back</a>

Upvotes: 3

Ab_Fredo
Ab_Fredo

Reputation: 106

you could do this easily with a simple one-liner JS

<button onclick="history.back()">Go Back</button>

This will take you back to the previous page of your history list. If you don't have a history https://www.w3schools.com/jsref/met_his_back.asp

Upvotes: 4

Koushik Das
Koushik Das

Reputation: 10813

You can use this

return redirect(request.META.get('HTTP_REFERER'))

Make sure to import this

from django.shortcuts import redirect

Upvotes: 16

Frank
Frank

Reputation: 2039

My favorite way to do that is giving the request.path as GET parameter to the form. It will pass it when posting until you redirect. In Class-Based-Views (FormView, UpdateView, DeleteView or CreateView) you can directly use it as success_url. Somewhere i read that it's bad practise to mix GET and POST but the simplicity of this makes it to an exception for me.


Example urls.py:

urlpatterns = [
    path('', HomeView.as_view(), name='home'),
    path('user/update/', UserUpdateView.as_view(), name='user_update'),
]

Link to the form inside of the template:

<a href="{% url 'user_update' %}?next={{ request.path }}">Update User</a>

Class-Based-View:

class UserUpdateView(UpdateView):
    ...
    def get_success_url(self):
        return self.request.GET.get('next', reverse('home'))

In your function based view you can use it as follows:

def createadv(request):
    uw = getuw(request.user.username)
    if request.method =='POST':
        form = AdverForm(request.POST, request.FILES)
        if form.is_valid():
            form.instance.user = request.user
            form.save()
            next = request.GET.get('next', reverse('home'))
            return HttpResponseRedirect(next)

    args = {}
    args.update(csrf(request))
    args['username'] = request.user.username
    args['form'] = AdverForm()
    args['uw'] = uw
    return  render_to_response('createadv.html', args)

Upvotes: 6

mandmeier
mandmeier

Reputation: 409

In case this helps someone I got this to work in class based UpdateView

template

<form class="form" method="POST">
    {% csrf_token %}

    <!-- hidden form field -->
    <input type="hidden" id="previous_page" name="previous_page" 
    value="/previous/page/url">

    <!-- any other form fields -->
    {{ form.name|as_crispy_field }}
    {{ form.address|as_crispy_field }}

    <!-- form submit button -->
    <button class="btn btn-primary" type="submit" id="submit">Submit</button>
</form>


<!-- JS to insert previous page url in hidden input field -->
<script>
    prev = document.getElementById("previous_page");
    prev.value = document.referrer;
</script>


views.py

class ArticleUpdateView(generic.UpdateView):

    model = Article
    form_class = ArticleForm
    template_name = 'repo/article_form.html'

    def form_valid(self, form):
        form.instance.author = self.request.user
        # if form is valid get url of previous page from hidden input field
        # and assign to success url
        self.success_url = self.request.POST.get('previous_page')
        return super().form_valid(form)

The view now redirects you back to the page where you had clicked the "Update/Edit" button. Any URL query parameters are also preserved.

Upvotes: 0

Antoine Pinsard
Antoine Pinsard

Reputation: 35032

You can add a next field to your form, and set it to request.path. After you processed your form you can redirect to the value of this path.

template.html

<form method="POST">
    {% csrf_token %}
    {{ form }}
    <input type="hidden" name="next" value="{{ request.path }}">
    <button type="submit">Let's Go</button>
</form>

views.py

next = request.POST.get('next', '/')
return HttpResponseRedirect(next)

This is roughly what django.contrib.auth does for the login form if I remember well.

If you pass through an intermediate page, you can pass the 'next' value via the querystring:

some_page.html

<a href="{% url 'your_form_view' %}?next={{ request.path|urlencode }}">Go to my form!</a>

template.html

<form method="POST">
    {% csrf_token %}
    {{ form }}
    <input type="hidden" name="next" value="{{ request.GET.next }}">
    <button type="submit">Let's Go</button>
</form>

Upvotes: 108

Selcuk
Selcuk

Reputation: 59445

You can use the HTTP_REFERER value:

return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))

Note that this will not work if the client disabled sending referrer information (for example, using a private/incognito browser Window). In such a case it will redirect to /.

Upvotes: 61

Related Questions