How to alter the URI in django? - python

http://packages.python.org/django_simple_feedback/ref/request-response.html tells that the absolute URI is built using the server variables available in this request. So, How can I alter the URI using HttpRequest.build_absolute_uri.
My situation is:
/foo/bar/2/ is the url having corresponding view load_view(request) Before rendering the template I want to alter the URI by attaching the new absolute URI in the request. So, that My templte renders on the URL /foo/.

You can use django.shortcuts.redirect to redirect to a different location:
def load_view(request):
return redirect('/foo/')
You will still need a corresponding view setup for that url, of course, as this will cause the user's browser to redirect to /foo/. If you want to change the url without refreshing the page, you can do this with HTML5 now:
window.history.pushState('','foo','/foo/');

Related

Django - Changing the url to redirect from a middleware on the fly

I'm building a SSO login meant to be used from links send by emails.
Each link should auto-connect the user (SSO), and be clickable multiple times (they have a TTL, which depends on the email)
It works fine, but I'm concerned about the end-user sharing his url on social networks (basically copy/pasting the url, which contains the SSO token), allowing anyone following the link to be logged in automatically.
My first attempt was to try to remove the GET SSO_TOKEN parameter, from my SSOMiddleware, as follow:
if remove_token_middleware:
request.GET._mutable = True # GET is not mutable by default, we force it
# Remove the token from the url to avoid displaying it to the client (avoids sharing sso token when copy/pasting url)
del request.GET[SSO_TOKEN_PARAM]
request.GET._mutable = False # Restore default mutability
return login(request, user) if service.get("auto_auth") else None
Basically, my thought was that since the SSO_TOKEN is in the request.get object, removing it from it would eventually change the url where the user gets redirected
In my controller, here is how the user gets "redirected" (using render)
return render(request, 'campagne_emprunt/liste_offres_prets.html', locals())
When using render, there is no redirection, and the SSO token is still visible in the URL (in the browser address bar).
Is there a way to somehow tell Django to change the destination url, on the fly?
So in order to redirect, there is a builtin redirect function of Django that you use instead of rendering I think .. give it a shot,
from django.shortcuts import redirect
def redirect_view(request):
response = redirect('/redirect-success/')
return response
and for reference-
https://realpython.com/django-redirects/

How do I access the next token of the url in django template?

In one of my template, I'm trying to access the next token or the name of the view I'm supposed to go to if I were logged. Is it possible to access this information within the template ?
Edit 1 :
What I would write in the url even though I'm not logged in :
http://127.0.0.1:8000/home
And this would redirect me there url wise :
http://127.0.0.1:8000/login/?next=home

To use Turbolinks 5 with Django, how can I automate inclusion of the Turbolinks-Location header when using redirect()?

According to the Turbolinks 5 documentation for "Following Redirects" (https://github.com/turbolinks/turbolinks#following-redirects):
When you visit location /one and the server redirects you to location
/two, you expect the browser’s address bar to display the redirected
URL.
However, Turbolinks makes requests using XMLHttpRequest, which
transparently follows redirects. There’s no way for Turbolinks to tell
whether a request resulted in a redirect without additional
cooperation from the server.
And the solution for this is to:
send the Turbolinks-Location header in response to a visit that was
redirected, and Turbolinks will replace the browser’s topmost history
entry with the value you provide.
The Turbolinks Rails engine performs this optimization automatically for non-GET XHR requests that redirect with the redirect_to helper.
I have a great interest in using Turbolinks on my Django (1.11) project and I'm wondering if anyone could point me in the right direction of how to create a new Django redirect() function or modify the existing one to always include the Turbolinks-Location header that is needed for redirects to function as expected. I definitely do not want to be manually setting this header every time I do a redirect.
There is a similar entry in the 'Redirecting After a Form Submission' section (https://github.com/turbolinks/turbolinks#redirecting-after-a-form-submission) I would also appreciate any help in understanding how to implement:
If form submission results in a state change on the server that
affects cached pages, consider clearing Turbolinks’ cache with
Turbolinks.clearCache().
The Turbolinks Rails engine performs this optimization automatically
for non-GET XHR requests that redirect with the redirect_to helper.
I did see there is a "Drop-in turbolinks implementation for Django" package on github but this is forked from turbolinks-classic and sourcecode has no mentions of the Turbolinks-Location header so I am sure this is not what I'm looking for.
I did end up discovering how to do exactly what I was attempting by being pointed to a blob of code in this project https://github.com/viewflow/django-material/blob/v2/material/middleware.py by a reddit user.
I copied the TurbolinksMiddleware class into my own middleware.py under my apps directory and listed it in my settings.py as such
# MIDDLEWARE CONFIGURATION
# --------------------------------------------------------------------------
MIDDLEWARE = [
.
.
.
'apps.middleware.TurbolinksMiddleware',
]
With the regular installation step of including the turbolinks.js in my html template, everything appeared to be working correctly.
Here is the TurbolinksMiddleware class in case it should not be available at the link above:
class TurbolinksMiddleware(object):
"""
Send the `Turbolinks-Location` header in response to a visit that was redirected,
and Turbolinks will replace the browser’s topmost history entry .
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
is_turbolinks = request.META.get('HTTP_TURBOLINKS_REFERRER')
is_response_redirect = response.has_header('Location')
if is_turbolinks:
if is_response_redirect:
location = response['Location']
prev_location = request.session.pop('_turbolinks_redirect_to', None)
if prev_location is not None:
# relative subsequent redirect
if location.startswith('.'):
location = prev_location.split('?')[0] + location
request.session['_turbolinks_redirect_to'] = location
else:
if request.session.get('_turbolinks_redirect_to'):
location = request.session.pop('_turbolinks_redirect_to')
response['Turbolinks-Location'] = location
return response
The django package you mentioned implements a middleware that is responsible for adding the headers. It seems that for old turbolinks the headers had different names. You might write your own middleware to support turbolinks 5.
Instead of submitting forms normally, submit them with XHR.
You can achieve this with plain django. Read the django CSRF doc - they explain in detail what is necessary.

Redirect to back to referrer page

I am building an account settings page. I was thinking of having a few routes that only accept post request then edit the records and then go back the account settings page.
The problem is that there is two account settings pages. One for users and one for an admin account.
The admin account_settings can use the same logic form the user account settings routes but If i use and post to use the user/account-settings route it returns back the user/account-settings route insted of the admin/user-account settings.
I was wondering how can flask returns back to the page it was on.
People usually solve this problem with session cookies (which you should have access to given that the user will be logged into an admin panel).
This is of course safter than using HTTP_REFERER (header sent by the client), as you control the contents of the session cookie entirely.
You could also pass a ?continue=http://... thing in the URL.
request.referrer will return back to the previous page. http://flask.pocoo.org/docs/0.11/reqcontext/

How to pass URL arguments after # sign in Django

If I send a link to a Django page which has #args in the URL, e.g.
http://localhost/someurl/?arg1=true&arg2=false#1970-01-01/2038-01-01/something_else
Then the person is not logged in - the login form appears. Unfortunately after successful login, it will redirect the person to:
http://localhost/someurl/?arg1=true&arg2=false
What I would like to keep somehow is also the #1970-01-01/2038-01-01/something_else
How can I do that in Django?
I would try modifying the code responsible for generating the link such that the # symbol is replaced by %23 (i.e. its percent encoding: https://en.wikipedia.org/wiki/Percent-encoding ).
The final URL would be:
http://localhost/someurl/?arg1=true&arg2=false%231970-01-01/2038-01-01/something_else

Categories