Django redirect behavior with back button - django

I'm running into an issue now where I have a "random" link on my site to see a random user. The way I have it set up is to get the user_id and then use redirect to serve the proper page. The issue I'm running into is if I click the random button multiple times, clicking on back will bring me back to the page before the "random" clicks.
To be more concrete, this is what's happening:
HomePage, Click Random (go to /user1/), Click Random (go to /user4/), Hit back (end up on HomePage). In this scenario I'd like to end up on /user1/
This is the random view method:
def Random(request):
user = helpers.GetRandomUser()
return redirect('user_display', user_slug=user.username)
The template just has a link to /random/ which gets routed to the above view.
Edit: Apparently it works as expected in Firefox but in Chrome. I'd like it to have the Firefox-like behavior everywhere.

So if I understand you correctly you click two times on a link to the same url (like /random_user/) and you respond with a random redirect. This seems quite unconventional and it doesn't sound so wrong that Chrome might view this as a single history entry.
To archieve your wanted behaviour across browsers simply generate the random url before you render your random user link.
As you want to use it in multiple views, write a custom template tag:
#register.simple_tag
def random_user_url():
user_url = # generate your random user url
return user_url
In your template:
{% load your_tag_lib %}
Random user
This way every click leads the browser to a different url and will be memorized as seperate history entry.

Use the following code to force the browser not to cache the page. So, clicking back button sends request to server and now you can catch it and redirect him to the desired page.
from django.views.decorators.cache import cache_control
#cache_control(no_cache=True, must_revalidate=True)
def func()
#some code
return

To be clear, when you say "Back Button" do you mean:
Browser Back Button
Your own creation of a Back Button
If 2, are you doing this via client side? Such as via javascript?

Related

Django redirect page does not update the view

I'm using the Django Framework on Google App Engine.
I have multiple forms on the same view, to submit to different URL.
Trouble is after I get a form submitted: even if the called method update the datastore and some data, the previous page (where the forms are put in) is not refreshed, showing the updated data.
I could solve this problem using jQuery or some javascrip framework, appending dinamically content returned by the server but, how to avoid it?
Suggestions?
Am I wrong somewhere?
A part of "secure.html" template
<form action="/addMatch" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Matches:
<br />
{% for m in matches%}
{{m.description}} ---> {{m.reward}}
{% endfor%}
the "/addMatch" URL view:
def addMatch(request):
form = MatchForm(request.POST)
if form.is_valid():
user = User.all().filter('facebookId =', int(request.session["pbusr"]))
m = Match(user=user.get(),description =form.cleaned_data["description"],reward=form.cleaned_data["reward"])
m.save()
return HttpResponseRedirect("/secure/")
else:
logging.info("Not valid")
return HttpResponseRedirect("/secure")
The view method whose seems not working:
#auth_check_is_admin
def secure(request):
model={}
user = User.all().filter('facebookId =', int(request.session["pbusr"]))
u = user.get()
if (u.facebookFanPageId is not None and not u.facebookFanPageId == ""):
model["fanPageName"] = u.facebookFanPageName
model["form"] = MatchForm()
model["matches"] = u.matches
else:
....
return render(request,"secure.html",model)
Francesco
Based on what you posted, it seems like you're redirecting properly and are having database consistency issues. One way to test this would be to look at the network tab in the Google Chrome developer tools:
Click on the menu icon in the upper right
Click on "Tools"
Click on "Developer Tools"
Click on "Network" in the thing that opened up at the bottom of the screen.
Now, there will be a new entry in the network tab for every request that your browser sends and every response it receives. If you click on a request, you can see the data that was sent and received. If you need to see requests across different pages, you might want to check the "Preserve log" box.
With the network tab open, go to your page and submit the form. By looking at the network tab, you should be able to tell whether or not your browser issued a new GET request to the same URL. If there is a new request for the same page but that request has the old content, then you have a datastore consistency issue. If there was NOT a new request that yielded a response with the data for the page, then you have a redirect issue.
If it turns out that you have a datastore consistency issue, then what's happening is the data is being stored, but the next request for that data might still get the old data. To make sure that doesn't happen, you need what's called "strong consistency."
In a normal App Engine project, you get strong consistency by putting entities in the same entity-group and using ancestor queries. I'm not certain of what database/datastore you're using for Django and how the different database layers interact with App Engine's consistency, so this could be wrong, but if you can give your users the right key and then fetch them from that key directly (rather than getting all users and filtering them by key), you might get strong consistency.

To stop a redirect back to logout when the login URL ends with ?next=/accounts/logout/ in Django

In my template I am currently using the next parameter to redirect the user back to the page before the login page with this:
Log in
The firstof tag makes sure that in case request.path is invalid, then it will redirect back to the root URL.
This works well on every page except one: the logout page. If I wanted to switch user, then I would first log out, then click log in. But then my url would be
http://127.0.0.1:8000/accounts/login/?next=/accounts/logout/
So as soon as I log in, I would immediately be logged back out again. How do I modify the template so with something like this pseudocode:
if request.path and request.path != reverse( 'auth_logout' )
return request.path
return "/"
The easiest solution I can think of, is add "?next=/" to your logout url, that way, as soon as the user logs out, he will be immediately redirected to the specified url, so no one will ever stay on logout page upon logout.
Otherwise you would have to rewrite the login view and add any custom logic you need, which would be easier if contrib.auth views were class views, which they are currently not unfortunately.
So copy paste it and modify :) (I know that copy pasting is bad, but thats the only way you could add custom behavior to it).
The view is located here:
https://code.djangoproject.com/browser/django/trunk/django/contrib/auth/views.py#L25

How to redirect to page which has GET parameters after login using the {{next}} variable in django

I am using allauth to provide registration and login in my django site. Everything else seems to be working fine other than that I am having problems to redirect the person to the current page after login.
I have a page where I have some interview questions and a typical url for it would be like
/questions/?company=google
This page contains a list of questions for the company google, but to view the answer the person needs to login. The answers are displayed in a dropdown box. However when the user clicks on login a request is sent to the login page as follows
/login/?next=/questions/
And the get parameter which was actually there in my actual page is not sent because of the & in my url. How can I solve this problem. It does not look nice that the person is redirected to a different page from where he/she tried to login.
I know sending the next parameter as a GET variable is not the solution, but is there a way I can send the redirect link as a POST variable from the template.
I tried another thing, in my view that displays the questions list. I set session variables which contains the url of the current link . If a user clicks on login, in my login view I check for this particular session variable. If it is set then I redirect to that page.
However the session variable is not received in the login view, I am not sure but I think the session is reset when the user goes to the login view.
Any suggestions are appreciated.
Have you tried
next = request.get_full_path()
This will return correct path with all queries ( see docs ) , you can then pass it as GET param to redirect url e.g.
full_path = request.get_full_path()
return HttpResponseRedirect('%s?next=%s' % (reverse('login'), full_path))
You should encode the URL-parameter in this case. You want to send a variable like /questions/?company=google, but as you mentioned the ?, = (amongst others) characters are special ones. It has a special meaning when embedded in the URL. If you encode the variable with URL encoding, it becomes %2Fquestions%2F%3Fcompany%3Dgoogle. If you assign that to the parameter next, the URL becomes: /login/?next=%2Fquestions%2F%3Fcompany%3Dgoogle. This should redirect to the correct place on login.

Django: Redirect to a page, then redirect back again?

As per the title: in Django views, can I redirect to a page using HttpResponseRedirect and then from that page, immediately redirect back again to the original page?
In other words, how can I get the second view to 'remember' the first one in order to redirect back there?
I want to do this to handle some LDAP authorisation.
Thanks!
You could redirect to /page2/?next=/page1/, then get the original url from the GET parameters in the view for page2.
# page2 viewl
next = request.GET['next']
return HttpResponseRedirect(next)
You probably want to avoid any session level logic. Your requirements have nothing to do with a session, so avoid using session level constructs.
You have a request level requirement, and the request level logic identified by Alasdair is what you want.
You could store the original URL in a session variable, and then pop off that value and use it to redirect back to the original page.

Django: How do I position a page when using Django templates

I have a web page where the user enters some data and then clicks a submit button. I process the data and then use the same Django template to display the original data, the submit button, and the results. When I am using the Django template to display results, I would like the page to be automatically scrolled down to the part of the page where the results begin. This allows the user to scroll back up the page if she wants to change her original data and click submit again. Hopefully, there's some simple way of doing this that I can't see at the moment.
It should already work if you provide a fragment identifier in the action method of the form:
<form method="post" action="/your/url#results">
<!-- ... -->
</form>
and somewhere below the form, where you want to show the results:
<div id="results">
<!-- your results here -->
</div>
This should make the page jump to the <div> with ID results.
It is complete client site and does not involve Django, JavaScript or similar.
You need to wrap your data into something like this:
<div id="some-id">YOUR DATA TO BE DISPLAYED</div>
and if you make redirect in your view you need to redirect to url: /some-url/#some-id
if you don't make redirect you need to scroll to the bottom using javascript (but note that redirect is preffered way to use in view after saving data).