How to redirect to previous page in Django after POST request

Viewed 72240

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.

7 Answers

You can use this

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

Make sure to import this

from django.shortcuts import redirect

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)

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

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.

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>

Related