How to send values via ajax from django template to views? - javascript

I have a select box that calls a function on changes. The function finds the selected value from "Products" selectbox.
I want to throw that selected value to my views.py which after some operations return the list of data and Populates the Destination's selectbox.
I want to use ajax for this purpose. Please help.
My code looks like this:
<script type="text/javascript">
function select_value()
{
var e = document.getElementById("Product");
var prod = e.options[e.selectedIndex].text
console.log(prod)
}
</script>
This is what my selectbox look like:
<table>
<tr>
<td>
<select id="Product" onChange="select_value();">
{% for products in product_name_list %}
<option>{{products|safe}}</option>
{% endfor %}
</select>
</td>
<td>
<select id="dest">
{% for des in destinations_name_list %}
<option>{{des|safe}}</option>
{% endfor %}
</select>
</td>
</tr>
</table>
This is my views.py:
def selection_filter(request,prod):
destination_objs = Destination.objects.filter(product=prod)
destination_name = destination_objs.values_list('name')
destination_name_list = []
for iter_name in destination_name:
destination_name_list.append(iter_name[0].encode('utf-8'))
return render_to_response('temp/test.html',
{"destination_name_list" : destination_name_list},
)

I think the point you might be misunderstanding is that your Django template for your whole page will not be re-rendered "magically". In Django's standard model-view-template paradigm, the template is rendered just once, upon the initial request. The way you've written it, unless there's a default product selection, you're going to have an awkward empty <select> in the first render. But ignoring that...
For a problem like this, you need two views: one for rendering the whole page, and one for providing the Ajax response. There are two main options for the second view: 1) return JSON for interpretation/rendering by your script post-response or 2) return a fully rendered HTML fragment for direct insertion into your DOM. In this case, I'd just go for option 2.
I recommend looking into Jquery, as it makes Ajax and DOM manipulation super simple.
If you've got Jquery, it's as simple as adding to your script:
$.get('/destinations/' + prod)
.done(function (html) {
$(#dest).html(html);
});
(You can do the same thing without Jquery too, but it requires a bit more wrangling)
Your test.html file should contain:
{% for des in destinations_name_list %}
<option>{{des|safe}}</option>
{% endfor %}

Related

use dropbox value in jinja if statement

I have a dynamic dropbox using jinja loop. As part of the condition, I want to use a value from another dropbox. For this, I am setting up a global variable using scenario_id = $('#scenario').val(); in an onchange function for the other combo. It works ok. I also show it on the page.
However, when I use scenario_id as part of the if statement, it does not work. It does not use the correct value. It is potentially null ( I am not sure).
So, the below code does not create a correct select field. If I replace the scenario_id with a static known id, it works okay for that selected scenario.
Can you please help me to be able to use dynamic value here?
Kind Regards,
Sofia
<SELECT name="source1" id="source1">
{% for node in allowed_values_nodes %}
{% if node[0]==edge.source_id and node[2]== scenario_id%}
<OPTION value = {{node[0]}} selected>{{node[1]}}</option>
{% endif %}
{% if node[0]!=edge.source_id and node[2]== scenario_id%}
<OPTION value = {{node[0]}}>{{node[1]}}</option>
{% endif %}
{% endfor %}
</SELECT>
I added the code already.

Replace a html div based on .onchange, passing in a variable

I am using Flask and wtforms to create a web page "index.html" that loads multiple forms. The selection of forms that are rendered depend on dropdown selections, and a variable "serviceid" updated from an API call. The form selection and rendering is handled in an included file "form_select.html", which requires "serviceid" value to pick the correct form. I am having trouble figuring out how to refresh the forms based on updated serviceid values without doing a full page reload.
I can use something like this with jinja2 include to render "form_select.html" and pass the "serviceid" variable so the right form is rendered:
<div id="loadform"> {% include './form_select.html' with serviceid %} </div>
This is working on first load, but I need to select a new form when the user selects a new value from a dropdown. I am running a script based on mydropdown.onchange, which first obtains the correct "serviceid" value, but now I need to rerender just the loadform div with this value.
I have tried approaches along the lines of the following - but I cant seem to figure out how to deliver this jinja2 with .innerHTML.
document.getElementById('loadform').innerHTML = `
{% with serviceid=serviceid %}
{% include './form_blocks.html' %}
{% endwith %}
`;
There is probably a better way to do this, but the examples I can find don't include passing in a variable. Can I use innerHTML for this, or is there a better way?

How to associate dynamic value with HTML elements?

I want to create a list which is clickable and which would allow me to take a survey when I click it.
{% extends "layout.html" %}
{% block title %}
Take Survey
{% endblock %}
{% block main %}
<div class="list-group">
{ for search in searches }
{{search.topic}}
{ endfor }
</div>
{% endblock %}
When I click it I want it to go to a page which shows the questions of the survey whose topic was being shown.
I have created SQL tables for users,surveys,questions and options. Surveys are linked to users, questions are linked to surveys and options are linked to questions.
I just need a way to access the survey id({{search.id}}) in my take route where I could run a SQL query using the survey id to link everything.
Just a disclaimer, I am a beginner in HTML so please try to explain elaborately.
There are multiple ways that you can do this with html, here are a few of them
create a hidden input with the value that u need, and later when u need it retrieve it from that input
<input type="hidden" id="searchId" name="searchId" value="3487">
add a custom attribute to an element, and later when needed retrieve it from that element
<div class="list-group">
{ for search in searches }
{{search.topic}} data-search-id="{{search.id}}"
{ endfor }
</div>
There are also multiple ways you can do this without html
insert a script that has the search id, and later retrieve that id from javascript
{% block main %}
<div class="list-group">
{ for search in searches }
{{search.topic}}
{ endfor }
<script>
// just make sure that this variable is unique, so u dont cause errors or overwrite another variable by mistake
const MY_APP_SEARCH_ID ={{search.id}}
</script>
</div>
{% endblock %}
You could also generate a unique url for each survey
{{search.topic}}
and then handle that search id from the \take endpoint

Python/Flask/HTML - Render HTML in new window instead of home page

I have a Python code where I'm using Flask to create a webpage. In the home page, I'm filling out a form, submitting using a button and it displays a table based on the inputs.
The problem i'm having is that once I click the button to submit the form, it renders the table on that same webpage. I would like to create a new window using JavaScript window.open() or whatever other method you might suggest to render that table inside the new window and leave the home page as it is. I tried looking around and I can't seem to get anything to work. I've read through this question and this question. But those suggestions don't seem to match what i'm looking for.
This is my code:
Python code
from flask import Flask, render_template, request,
app = Flask(__name__)
def get_table(user_input):
...
return dict //returns list of dictionaries, for example...
//dict = [{'name':'Joe','age':'25'},
// {'name':'Mike','age':'20'},
// {'name':'Chris','age':'29'}]
#app.route("/")
def home():
return render_template('home.html')
#app.route("/table", methods = ['POST'])
def table():
user_input = request.form['input']
dict_table = get_table(user_input) //return list of dictionaries
return render_template('table.html', dict_table=dict_table)
if __name__ == '__main__':
app.run(debug=True)
home.html
<!DOCTYPE html>
<html>
<head>
<title>Homepage</title>
</head>
<body>
<form action="/table" method="post">
<select name="input">
<option value="1">Input</option>
</select>
<button type="submit">Click Me!</button>
</form>
</body>
</html>
table.html
<!DOCTYPE html>
<html>
<head>
<title>Table</title>
</head>
<body>
<table id="table">
{% if dict_table %}
<tr>
{% for key in dict_table[0] %}
<th>{{ key }}</th>
{% endfor %}
</tr>
{% endif %}
{% for dict in dict_table %}
<tr>
{% for value in dict.values() %}
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</body>
</html>
Could someone explain in a clear way how I can click the form submit button on my homepage, stay on the homepage home.html, and make the table from table.html open up in a new window (maybe using window.open() from JavaScript or something else)?
I would appreciate it if someone could walk me through the steps on how to do this with my code provided and show me specifically where to call functions and things like that. I'm new to Flask/HTML/JS and I'm just trying to learn for personal use and I'm getting frustrated reading links and documents that show just how to display a URL like google.com in a new tab, which is not what I want. Thanks!
Step1: Check out this link that explains how to use Jquery and Ajax with FLASK
The key concept here is AJAX (asynchronous JavaScript and XML). In short, it is an architecture that makes it possible to send requests to the server in the background (called Asynchronous requests) and then modifies the content of the page currently displayed by the web browser according to the result received from the server, avoiding as well as the server does not transmit the complete page again.
Step2: A solution to your problem
First we write the routes:
from flask import Flask, render_template, request,
app = Flask(__name__)
user_input = None
def get_table(user_input):
...
return dict # returns list of dictionaries, for example...
# dict = [{'name':'Joe','age':'25'},
# {'name':'Mike','age':'20'},
# {'name':'Chris','age':'29'}]
#app.route('/')
def home():
return render_template('home.html')
#app.route('/_ajax_user_input')
def ajax_user_input():
global user_input
user_input = request.args.get('user_input', 0, type=int)
return "ok"
#app.route("/table")
def table():
x = user_input
dict_table = get_table(x) # return list of dictionaries
return render_template('table.html', dict_table=dict_table)
After we attack the templates:
home.html:
<select id="input" name="input">
<option value="1">Input</option>
</select>
<button type="button" class="test"> Click Me! </button>
<script>
$(document).ready(function(){
$('.test').bind('click', function() {
$.getJSON($SCRIPT_ROOT + '/_ajax_user_input',{
user_input: $('#input').val(),
},function() {
window.open('http://127.0.0.1:5000/table', '_blank');
});
return false;
});
});
</script>
table.html:
<table id="table">
{% if dict_table %}
<tr>
{% for key in dict_table[0] %}
<th>{{ key }}</th>
{% endfor %}
</tr>
{% endif %}
{% for dict in dict_table %}
<tr>
{% for value in dict.values() %}
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
Basically here is what happens:
when I click on my button, I call the Javascript script:
$('.test').bind('click', function() {
This sends an ajax request to FLASK, which consists in executing the ajax_user_input() function:
$.getJSON($SCRIPT_ROOT + '/_ajax_user_input',
To this function I send a data (the value selected by the user in the select tag) and this data is stored in the variable user_input:
user_input: $('#input').val(),
On the side of Flask I get the data and I store it in a global variable that I named user_input too:
global user_input
user_input = request.args.get('user_input', 0, type=int)
Then in my script I call a javascript method that allows me to open a url in a new tab (more details here):
window.open('http://127.0.0.1:5000/table', '_blank');
The 'table' route, stores in the variable x the data previously stored in my global variable (user_input), then it calls the function get_table() (by passing him the variable x in parameter) which returns a list of the dictionaries, and finally it returns the page table.html with the list of the dictionaries in parameter:
x = user_input
dict_table = get_table(x)
return render_template('table.html', dict_table=dict_table)
I hope this will help you, even though I am convinced that there are many other ways to do it, perhaps more effective.

Django - Update page with ajax data

[Edited for more clarity]
My problem is more of an architecture problem, I have thoughts of many ways to do what I need to but can't figure out which one is correct/the best, so here it is.
I fetch some xml from a remote webserver using ajax, then parse it with jquery.What I want is that when the page is first rendered I have some "loading" gifs, one for each ajax request i'll be making , then when the data is fetched, it appears on the page.
The things is I want to have jquery post these data to the view to render it. ( This is for the other developers who will be using my app, who don't know much of javascript and prefer to write python/html to code the way they want the data to be displayed and make use of the django template engine for custom tags and stuff)
The question is how can I distinguish between the first loading of the page where we have no data and the second time where we have the data. I don't want to have to refresh the page at any time. I thought of having something in the template like :
{% block content %}
{% if not data %}
it's the first loading of the page,we have to fetch the data.
<p> My first item : some loading logo </p>
<script>
call a static script that gets the data then appends it to the html/post it back.
</script>
{% endif %}
{% if data %}
the data had already been fetched so we can display it, something like :
<p> My first item : {{first item}} </p>
{% endif %}
{% endblock %}
I have looked on other questions but it is usually updating with data from the database. Sorry if the question is too specific but I want to really have a good design of the problem before starting to write code and I'm a bit lost. Thank you .
Why do you want to send the parsed data back to the server just for transforming it into Html ?
Why not just use some kind of Javascript based rendering library that can do this ? Your appliation would perform faster since you don't need to execute an extra request.
Django tags and context dict are resolved when template is rendered for the first time.
AJAX is used to post/fetch data withoud page reload, so after AJAX request your page will not be reloaded - and django template renderer will have no possibility to show updated data.
But you could use jQuery get() or post() to retrieve rendered template from other django view and integrate it into current page.
This template must be rendered at request on /ajax/fetch/:
{% block content %}
{% if not data %}
it's the first loading of the page,we have to fetch the data.
<p> My first item : some loading logo </p>
<script>
call a static script that gets the data then appends it to the html/post it back.
</script>
{% else %}
the data had already been fetched so we can display it, something like :
<p> My first item : {{first item}} </p>
{% endif %}
{% endblock %}
And this is sitting on your main page:
<script [include jquery here]></script>
<script>
$(function(){
$("#get_data_please").click(function(){
$.get('/ajax/fetch/', function(data) {
// this is called on ajax success
$('#ajax_result').html(data);
});
});
});
</script>
...
Click to get data
<div id="ajax_result">
Here all will be loaded
</div>

Categories