Django new session for each browser tab - python

I have a problem with Django session and i have no idea how to solve it. Basically i store some data in the session dictionary in one view function, and calculate some thing in a second function using the values from the first view. Now if someone opens up two tabs, fills in the data in one and submits it, fills the second tab and submits it, the session dictionary will be the same for both tabs. I hope i phrase myself right.
Simple explanation:
def a(request):
request.session["q"] = request.POST.get('q')
def b(request):
while True:
print(request.session["q"])
So lest assume function a is rendering an index page, and getting a value from there. On a button push in this index page function b is called. Now if i open two tabs, input 1 in to the index page and submit i ll see a lot of 1 in the terminal. Now i open up another tab, input 2, submit, the printing will change.
What i would like to do is to keep separate sessions (separate information to come in and go out) from my server to the user on different tabs of a browser.
I am sorry if i phrase myself wrong, this is the first time i am trying to work with web servers.
EDIT:
As i mentioned in the comments the answer is currently not working, and i think it is just a syntax error, however i dont know where i gone wrong.
My template:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
{% load staticfiles %}
<HTML>
<HEAD>
<LINK rel="stylesheet" type="text/css" href="{% static 'style7.css' %}"/>
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-0.12.13.min.js"></script>
<link rel="stylesheet" href="http://cdn.bokeh.org/bokeh/release/bokeh-0.12.13.min.css">
<script type="application/javascript">function makeid() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 5; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
document.getElementById("session").value = makeid();</script>
</HEAD>
<BODY>
....
....
<form action="{% url 'raw' %}" method="post" style="float: left;">{% csrf_token %}<input type="hidden" name="session" id="session"><input type="submit" value="Download text"/></form>
....
My view function:
def plot(request):
print(request.POST.get("session"))
....
However in the terminal see nothing printed, thus i think the variable is an empty string.

i don't know what app you are making but lets say i want to save the username as session.
1. we need to create a script that create a random code and assign it to and hidden input
function makeid() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 5; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
window.onload = function() {
document.getElementById("session").value = makeid();
}
2. in the form that you take the data from user add a new hidden input
<form>
...
<input type="hidden" name="session" id="session">
</form>
3. now when the user submit the form to a view we need to do this in the view
def someview(request):
session_id = request.GET.get('session')
username = request.GET.get('username') # or any data...
request.session['username_%s' % session_id] = username
# now lets say you want to redirect the user to the next page...
# you have to send the 'session_id' to it and always send to
# the next view then in that view retrieve his name like this
# ``name = request.session['username_%s' % session_id] ``
# the session_id from the old view
so the urls should be like this:
/first-step/?session=somecode.
/second-step/?session=somecode
if you have more fields you have to save them in session and retrieve them as i did, hope it helps you, i know its complex!
bye :)

Related

posting input data from html to python script with ajax

I am wanting to POST a user inputted data in an html file to a Python script with AJAX and have the Python script return it so that it shows up in a specific div in the html file.
HTML
<!DOCTYPE HTML>
<html>
<head>
<title>AJAX Test</title>
<script src="http://code.jquery.com/jquery-3.3.1.js"></script>
<script>
function test()
{
var message = $('input[name=message]').val();
$.ajax({
url: "/cgi-bin/hello.py",
type: "POST",
data: {"text" : message},
success: function(response){
$("#div").html(response);
}
});
};
</script>
</head>
<body>
<form>
Enter Message: <input type="text" name="message">
<input type="submit" value="submit" onclick="test()">
</form>
<div id="div">Default Message</div>
</body>
</html>
Python
#!/home/user/virtualenv/test/3.5/bin/python
import cgi, cgitb
cgitb.enable()
data = cgi.FieldStorage()
print "Content-Type: text/html\n"
print data
When I type a message into the input box and press the submit button, nothing happens. I am new to this so I feel like I am probably not understanding how this works. Any help would be appreciated!
Edit: Console is showing Uncaught TypeError: $.ajax is not a function
Edit 2: The first problem was due to using the slim version of jquery. After fixing that, nothing is happening on the page when I input and click submit.
The problem was that the form was submitting when I clicked the button. The solution was to change the input type to <button value="Submit" onclick="test()">.
The next problem was that python was returning FieldStorage(None, None, [MiniFieldStorage('text', 'blahblah')]). The solution was to access the value by using print (data["text"].value)

How to create html using user input and display it in a new tab?

I would like to run a flask application where the user can provide some user input which is used to create a HTML page which should then be displayed in a new tab. The HTML is created using an external tool (here mimicked by the function get_html which actually takes the user input as argument), so I cannot just use a template which I render (I think).
I can already take the user input and create the HTML I would like to see displayed, however, I did not manage to also open a new tab for it. How can this be achieved?
Here is my code:
from __future__ import print_function, division
from flask import Flask, render_template, request, jsonify
import json
# Initialize the Flask application
app = Flask(__name__)
#app.route('/html_in_tab')
def get_html():
# provided by an external tool
# takes the user input as argument (below mimicked by a simple string concatenation)
return '<!DOCTYPE html><title>External html</title><div>Externally created</div>'
#app.route('/_process_data')
def data_collection_and_processing():
# here we collect some data and then create the html that should be displayed in the new tab
some_data = json.loads(request.args.get('some_data'))
# just to see whether data is retrieved
print(some_data)
# oversimplified version of what actually happens; get_html comes from an external tool
my_new_html = get_html() + '<br>' + some_data
print(my_new_html)
# this html should now be displyed in a new tab
return my_new_html
#app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
The index.html looks as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="header">
<h3 class="text-muted">Get new tab!</h3>
</div>
<button type="button" id="process_input">Process!</button>
<a href="/html_in_tab" class="button" target='_blank'>Go to results</a>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
// clicking the button works fine: data is processed correctly
$('#process_input').bind('click', function() {
$.getJSON('/_process_data', {
some_data: JSON.stringify('some data')
});
// can this be changed to show the processed html?
window.open("/html_in_tab", "_blank");
return false;
});
});
</script>
</body>
</html>
So, now the window.open part opens a new tab, but it should display my_new_html, the newly created HTML by data_collection_and_processing. How can I achieve that?
At the moment you're just opening a new window at the endpoint "/html_in_tab" which will hit the Flask route for get_html() and show the standard HTML with no user input.
One method you could try is to open a new window and set the document body innerHTML with the updated content:
<script type="text/javascript">
$(document).ready(function() {
$('#process_input').bind('click', function() {
$.get('/_process_data', {
some_data: JSON.stringify('some data'),
}).success(function(data) {
var win = window.open("", "_blank");
win.document.body.innerHTML = data;
})
return false;
});
});
</script>
Change your html as shown below:
<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="header">
<h3 class="text-muted">Get new tab!</h3>
</div>
<button type="button" id="process_input">Process!</button>
<a href="/html_in_tab" class="button" target='_blank'>Go to results</a>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
// clicking the button works fine: data is processed correctly
$('#process_input').bind('click', function() {
$.getJSON('/_process_data', {
some_data: JSON.stringify('some data')
});
// can this be changed to show the processed html?
window.open("/process_data", "_blank");
return false;
});
});
</script>
</body>
</html>
and Python script as shown below:
from __future__ import print_function, division
from flask import Flask, render_template, request, jsonify
import json
# Initialize the Flask application
app = Flask(__name__)
#app.route('/html_in_tab')
def get_html():
# provided by an external tool
return '<!DOCTYPE html><title>External html</title><div>Externally created</div>'
#app.route('/_process_data')
def data_collection_and_processing():
# here we collect some data and then create the html that should be displayed in the new tab
some_data = json.loads(request.args.get('some_data'))
# just to see whether data is retrieved
print(some_data)
# oversimplified version of what actually happens; get_html comes from an external tool
my_new_html = get_html() + '<br>' + some_data
with open('templates/changed_html.html','w') as f: #write the html string to file
f.writelines(my_new_html)
# this html should now be displyed in a new tab
return ''
#app.route('/process_data')
def process_data():
return render_template('changed_html.html')
#app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)

Returning a static HTML file with # fragment pointing to an <section> element

Say a website www.example.com has a with id="section_two". This section is offscreen. I can make this website load with this section onscreen by calling the URL www.example.com#section_two.
Now, say I'm trying to return a static index.html file using Bottle.py, but specifically I'm trying to return it with a onscreen that would otherwise offscreen. How can I return a URL of the form www.example.com#section_two?
Do you mean that you want a user to receive a html page already scrolled to the necessary section? It is not possible without some in-browser JavaScript. You can add something like this to your html (with JQuery):
<head>
...
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script>
$(function() {
$('#section_two').get(0).scrollIntoView();
});
</script>
</head>

web.py and how to use section blocks

I use web.py Templator for my project and using the render('templates', base="") I combine a base layout with a page specific layout (simplified).
view.py
render = web.template.render('templates',base='layout')
return render.index()
shared layout file
layout.html
$def with (content)
<html>
<head>
<title>$content.title</title>
</head>
<body>
$:content
</body>
</html>
page specific template
index.html
$def with (values)
$var title: Hello Kitty
<p>Hello $values, how are you doin?</p>
The solution I'm looking for is how to achieve the following
login.html
$def with (values)
$var title: Enter credentials
<form>
<p><input type="text" name="user_name"></p>
<p><input type="password" name="user_pwd"></p>
<p><button type="submit">Open the gates</button></p>
</form>
$block_begin
<script>
// When the form is submitted, check the required fields and inform user
// if any data is missing or looks weird
</script>
$block_end
</body>
</html>
My question is, how do I add the script to the login.html template but not the index.html template? I'm not interested in having to add all JS logic to all pages, I would like to add this $block_begin/$block_end so that it appears at the bottom of the layout.html like this
layout.html
$def with (content)
<html>
<head>
<title>$content.title</title>
</head>
<body>
$:content
$block_begin
$block_end
</body>
</html>
The $block_begin/$block_end was just something I came up with to better explain myself.
Just to be clear, template -> defwith sections is a grammar, not an example. To use templates, check http://webpy.org/docs/0.3/templetor for examples.
At a high level, you create templates similar to
=== templates/index.html ===
$def with(values)
$var title: Hello Kitty
<p>Hello $values, how are you doin?</p>
=== templates/layout.html ===
$def with(content)
<html>
<head>
<title>$content.title</title>
</head>
<body>
$:content
</body>
</html>
Then in your python you render the template, passing in any parameters specified in the template. ("values" in this example.) The named template (index.html) is render using the base (layout.html), and as you've discovered, content contains the rendered internal bit (the results of index) and is inserted into the base template, layout.
You're asking how to get some script into login.html, but not in index.html & that's easy: just add the javascript code into the login.html template.
=== login.html ===
$def with (values)
$var title: Enter credentials
<form>
...
</form>
<script>
window.addEventListener('load', function () {
// whatever javascript you want to execute on load.
// If using jQuery, you'll have to use $$('form') or jQuery('form') rather
// than $('form'), as dollar signs are special within the template.
});
</script>
Something more clever? Use content more fully. Anything you define using $var in your template gets put into $content in the base layout.
If you want to include login.js only when your login.html page is rendered, you could simple create a new content attribute. In login.html:
$var extra_js: js/login.js
Then, in your layout file conditionally load the value at the bottom (where we like to load scripts).
=== templates/layout.html ===
...
<body>
$:content
$if content.get('extra_js', None):
<script type="text/javascript" src="$content.extra_js"></script>
</body>
</html>
You can make your layout.html more and more powerful, parameterizing meta data, scripts, css files, etc. Just like you did with $content.title, and let your individual template files drive different parts of the overall layout.

Web Form with Web.py on PythonAnywhere

I'm trying to make a simple web script using the PythonAnywhere.com's web.py platform.
My intention is to create a simples Form which gets the data of textboxes and is able to work with them just like we do with PHP and so.
This is my main script:
import web
from web import form
import MySQLdb
render = web.template.render('/home/user/templates/')
conn = MySQLdb.connect("mysql.server","user","*********","userdb")
curs = conn.cursor()
curs.execute('''create table if not exists Dados (
id int not null auto_increment primary key,
nome varchar(200),
item1 varchar(50),
item2 varchar(50),
item3 varchar(50),
item4 varchar(50),
item5 varchar(50));
''')
urls = (
'/', 'index'
)
formula = form.Form(
form.Textbox('Nome', id='nome'),
form.Textbox('Item 1', id='it1'),
form.Textbox('Item 2', id='it2'),
form.Textbox('Item 3', id='it3'),
form.Textbox('Item 4', id='it4'),
form.Textbox('Item 5', id='it5'),
)
class index:
def GET(self):
form = formula()
return render.formtest(form)
def POST(self):
form = formula()
return render.finaliza(form['Nome'].value)
# comment out these two lines if you want to use another framework
app = web.application(urls, globals())
application = app.wsgifunc()
Then I have two templates in HTML, this one stores the Form:
$def with (form)
<form name="main" method="post">
$:form.render()
<input type="submit" name="send" id="envia" value="Ok" /> </form>
And this should give the result after the POST:
$def with (nome)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
Congratulations $:nome !
</body>
</html>
Everything works fine until a press the Ok button.
It shows the right template but doesn't show the $nome variable.
You can check this behavior on this link:
http://jonathan_hepp.pythonanywhere.com/
I'm beginning on web.py and PythonAnywhere so there must be something I'm doing wrong but I can't find it out.
Could you please help me out?
Thanks.
EDIT:
I've just find out now that if I pass the textbox value as a string the result is different.
The result page says "Congratulations None!"
That makes me think that actually the POST is not recieving the value I'm typing in the textbox. So the code seems to be ok but somehow I didn't make it right so it cannot reach the value in the form's input.
Still not working.
SOLVED:
Ok. I realized that the form.Form() option doesn't really create and html form output.
Actually when you look at the source code of the formtest page you see that what I supposed was the form appears as a simple .
So I just made the form into the formtest template directly in html an now it works pretty well.
Just a dumb mistake, but if somebody else comes throught it, just do the same.
Thank you all.
It seems like the variable in the finaliza template should actually be "Nome". So:
Congratulations $:Nome !
Might do the trick. Remember to restart your web app on the Web tab of PythonAnywhere after making changes or you won't see them.
I am using the same web.py framework. when I try to access it via localhost and URL after is /templates/tutorial.html
then I can see "send" button but with these $ signs
$def with (form, text)
$:form.render()
$text
Here is tutorial.html
$def with (form, text)
<head>
<title>Python and AJAX tutorial for beginners with webpy and jQuery</title>
<link rel="stylesheet" type="text/css" href="/static/tutorial.css" />
<script type="text/javascript" src="/static/jquery.js"></script>
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery(".button").click(function() {
var input_string = $$("input#textfield").val();
jQuery.ajax({
type: "POST",
data: {textfield : input_string},
success: function(data) {
jQuery('#foo').html(data).hide().fadeIn(1500);
},
});
return false;
});
});
</script>
</head>
<body>
<br>
<form class="form" method="post">
$:form.render()
<input class="button" type="submit" value="send"/>
</form>
<br><br>
<span id="foo">$text</span>
</body>
How I can get the values of these variables ?
$def with (form, text)
$:form.render()
$text

Categories

Resources