Reputation: 847
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
Reputation: 59
Use HTTP_REFERER
value:
for use in func return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
for use in template <a href="{{request.META.HTTP_REFERER}}">Go Back</a>
Upvotes: 3
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
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
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
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
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
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