Tornado redirecting to page with parameters - python

I'm using self.render to render a html template, which is dependent on the information received from the client via ajax in the def post() method like this:
class aHandler(BaseHandler):
#tornado.web.authenticated
def post(self):
taskComp = json.loads(self.request.body)
if taskComp['type'] == 'edit':
if taskComp['taskType'] == 'task':
self.render(
"tasks.html",
user=self.current_user,
timestamp='',
projects='',
type='',
taskCount='',
resName='')
However this does not redirect the user to the html page 'tasks.html'.
However I see in my console a status:
[I 141215 16:00:55 web:1811] 200 GET /tasks (127.0.0.1)
Where '/tasks' is an alias for tasks.html
Why wouldn't this be redirected?
Or how can data received from ajax, then be used to redirect to the tasks.html page along with all the parameters supplied in the above self.render request?

"render" never redirects a visitor's browser to a different URL. It shows the browser the contents of the page you render, in this case the "tasks.html" template.
To redirect the browser:
#tornado.web.authenticated
def post(self):
self.redirect('/tasks')
return
More info in the redirect documentation.
To redirect using an AJAX response, try sending the target location from Python to Javascript:
class aHandler(BaseHandler):
#tornado.web.authenticated
def post(self):
self.write(json.dumps(dict(
location='/tasks',
user=self.current_user,
timestamp='',
projects='',
type='',
taskCount='',
resName='')))
Then in your AJAX response handler in Javascript:
$.ajax({
url: "url",
}).done(function(data) {
var url = data.location + '?user=' + data.user + '&timestamp=' + data.timestamp; // etc.
window.location.replace("http://stackoverflow.com");
});
More about URL encoding is at this answer.

Related

Cannot access cookies after redirect in django

Here is situation I've dealt with. I will try to explain as much as easier to understand.
I want user to click on a button in the website (let's name this site A) which fires an ajax post request to django view. Within this view I have response.set_cookie to set cookie with data that is passed along with ajax post request.
After success response, then I quickly redirect page to different website (let say this site is B). When page loads, I want to access cookies what I've set from site A but cannot access.
Below is my code.
index.html (in site A, where the ajax post request is made)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button onclick=setCookies()>Create Invoice</button>
</body>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script type="text/javascript">
const setCookies = () => {
...some codes...
const xhr = new XMLHttpRequest()
const data = {
'HTTP_LOGIN_TYPE': 'admin',
}
$.ajax(
{
type: 'POST',
url: url, // hits endpoint where sets cookies.
crossDomain: true,
data: data,
success: () => {
window.location.href = to site B
},
error: xhr => {
console.log(xhr.responseText)
}
}
)
}
</script>
</html>
views.py (in site B, where sets the cookies)
from django.http import HttpResponse
from django.conf import settings
from rest_framework.views import APIView
class AuthenticateUser(APIView):
def post(self, request):
data = request.POST
login_type = data['HTTP_LOGIN_TYPE']
if login_type == 'admin':
response = HttpResponse(
'Setting login_type to %s' % login_type)
response.set_cookie(
'login_type', login_type, max_age=604800, domain=settings.SESSION_COOKIE_DOMAIN)
return response
views.py (in site B, redirected from ajax call in index.html, where I want to access cookies)
import re
from django.db import DatabaseError
from rest_framework.response import Response
from rest_framework.renderers import TemplateHTMLRenderer
from rest_framework.views import APIView
class GetInvoice(APIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'student/base.html'
def get(self, request, student_id):
login_type = 'hello'
if 'login_type' in request.COOKIES:
login_type = request.COOKIES['login_type'] # Can't access cookies
... more code ...
FYI, url in index.html and site B's domain are same, though site A and B's domains are different.
I am not sure what am I missing. I've been searching articles, posts, etc for last couple days and tried based on them but no luck.
Correct me if I missed anything.
Thanks in advance.
Because of the Same-origin Policy, you cannot access the cookies for a different domain.
Access to data stored in the browser such as localStorage and
IndexedDB are separated by origin. Each origin gets its own separate
storage, and JavaScript in one origin cannot read from or write to the
storage belonging to another origin.
However, if domain B is a subdomain of A, it will automatically have visibility into the cookies for domain A. If you cannot change the domains, you should redirect to site B with the cookies in the request headers/body.

Pass data from Django view to template

I have a very basic view that is supposed to render a page and pass some data to this page, here is how i do it:
def myview(request):
request = mydb.objects.filter(user=request.user)
return render(request,
"main/mytemplate.html",
context={"data":request})
When the page is loaded, the data is passed to the template, so to show that data, i'll only have to go to my html and add this:
{{data}}
But how can i do the same from a view that is not the same view that renders the page?
Let's say that this is a view that i can call with an Ajax request, so when the Ajax request is triggered, the view should send data in the same way and i want to be able to use it in the Django template language.
Here is an example:
def secondview(request):
request = mydb.objects.filter(item='free')
return HttpResponse(request)
This view is called from an Ajax request, it will send a response with the data, but i don't want to get the data in this format or in json format, instead i want to use it from the Django template language, just as i did with the first example. Is there any way to do it? Or can i only pass data to the template in the context?
1) Instead of returning HttpResponse in your secondview do this
def secondview(request):
from django.template.loader import render_to_string
x = 1
return render_to_string('template_name.jinja', locals())
2) If you want to display that response in your html, do this in your html,
<div id="x"> </div>
function someFunc(){
$.ajax({
url: "someurl",
type: 'GET',
success: function (response) {
document.getElementById("x").innerHtml = response
},
error: function (xhr, err) {
console.log(xhr.responseText);
},
cache: false,
contentType: false,
processData: false
});
I hope I've answered all of your questions, if not let me know.
def myview(request):
request = mydb.objects.filter(user=request.user)
context = {"data":request}
return render(request, "main/mytemplate.html", context)

Django redirects - how to handle redirect when using ajax

I need return redirect(url) or something like this in django, and force template to do to this url.
It returns me template html-code instead when EXACTLY redirect is required.
Any ideas? Now i have to write redirect in templates window.location='url' , it works, but make code tangled.
django.__version__ == '2.0.1'
I need django text, that does like javascript window.location='myurl'
Part of view
#csrf_exempt
def CheckState(request):
...
try:
... if (condition):
a = redirect('/mypage/')
...
return a #redirect('http://localhost:port/mypage/')
part of template (js.code)
$(document).ready(function() {
$.get('/my/CheckState/', {})
.success(function(data){
console.log(data);
//window.location = 'url' works here, otherwice no redirect!
//In console i see html-code of 'http://localhost:port/mypage/'
})
.error(function(xhr, textStatus, errorThrown){
console.log(xhr.responseText);
})
--comment--
a._headers = {'content-type': ('Content-Type': 'text/html; charset=utf-8'),
'location' : ('Location', '/mypage' )}
I saw this header before i asked question, but problem exists - no jump doing. Why is this redirect not working?
It's not possible to prevent $.get() (which uses Xmlhttprequest) from following the redirect. See this question for an explanation.
You might be able to use the fetch API which does allow you to prevent redirects.
If you can't do that, you could change the view to return the new URL in the response,
from django.http import JsonResponse
def CheckState(request):
return JsonResponse({'status': 'redirect', 'url': '/new/url/'})
...
Then in your ajax handler, check the response for status=redirect, and if so set window.location to the url.

Saving the HTML of a Flask web page generated from a form submit gives 400 output

Whenever I try to save the HTML of a web page generated in Flask from a form submission on my local test server, the saved page gives this output:
Bad Request
The browser (or proxy) sent a request that this server could not
understand.
I can save other pages of my app with no issue, it is only pages that are submitted through a form.
The snippet of the Flask url route in question, this is hit from a form on another url:
#app.route('/profile', methods=['GET', 'POST'])
def profile():
dist_type = request.form['district-select']
dist_num = int(request.form['district-number'])
json_data = {
'dist_type' : dist_type,
'dist_num' : dist_num
}
return render_template('profile.html', data = json_data)
The HTML template 'profile.html' is filled out with json_data:
<script type="text/javascript">
var data = {{ data|tojson|safe }}
</script>
<div class="distr-head" id="distr-type">{{data['dist_type']}}</div>
<div class="distr-head" id="distr-num">{{data['dist_num']}}</div>
When I Ctrl + S to save this filled template IN MY BROWSER, or link it to other sites, I cannot access the HTML and instead get a 400 Bad Request
request.form is not populated during a GET request, only during POST (and PUT, etc.). Trying to access a key on request.form when it doesn't exist raises a 400 error. You should guard the code that expects form data so that it only executes during a POST request.
#app.route('/profile', methods=['GET', 'POST'])
def profile():
data = None
if request.method == 'POST':
data = {
'dist_type': request.form['district-select'],
'dist_num': int(request.form['district-number'])
}
return render_template('profile.html', data=data)

reCATPCHA redirect isHuman=false

Hi I added reCAPTCHA to a page so far that it can verify a client. Now I want a more graceful failure when isHuman = Falsewith a redirect to the form page in such case with a message on the form page that reCAPTCHA failed. Can you inform what to do rather than just outputting "captcha failed?" so that it can redirect to the form page with Google App Engine's request handler? Here's my code:
def post(self, view): #edit
challenge = self.request.get('recaptcha_challenge_field')
response = self.request.get('recaptcha_response_field')
remoteip = os.environ['REMOTE_ADDR']
cResponse = captcha.submit(
challenge,
response,
CAPTCHA_PRV_KEY,
remoteip)
if cResponse.is_valid==True:
isHuman=True
else:
isHuman=False
self.response.out.write('captcha failed')
return
If you are just looking for a way to redirect back to your original posting page you can use:
self.redirect('your_url')
You could also include a GET variable in the url so that the page is aware that the CAPTCHA failed.

Categories

Resources