Pass arguments to a django template using AJAX - javascript

I am new with Django and JavaScript and I am struggling trying to pass some values from a html table rendered with django-tables2
I want to open a django template passing 3 arguments.
I have an html table with a drop down button with several options.
every open a different django template. I get the values from the table with this JS function:
<script type="text/javascript">
function param(){
$(function(){
var http = new XMLHttpRequest();
var tbl = document.getElementById("myTable");
var rows = tbl.rows;
var url = "/recepcion/";
for (var i = 0; i < rows.length; i++){
rows[i].onclick = function(){
idpro = this.cells;
ano = this.cells;
mes1 = this.cells;
$.ajax({
type:"POST",
url: "/recepcion/",
datatype: "json",
data: ({idprov: idpro[0].innerHTML, anio: ano[1].innerHTML, mes: mes1[2].innerHTML }),
success: function(){
http.open("POST",url,true),
http.send(data)
}
});
}
}
});
}
</script>
The functionality that i need is: When I click in the first option of the drop down button call this function. The function will take the value from some cells and pass this values as arguments to another template where i can edit some record.
This is the view where I try to pass the arguments
views.py
def RecepcionView(request):
idp = request.POST.get('idpro')
year = request.POST.get('year')
month = request.POST.get('month')
if request.method == 'POST':
r = DetalleRecepcion.objects.get(id_proveedor=idp,year=year,month=month)
form = RecepcionForm(request.POST, instance=r)
if form.is_valid():
form.save()
return HttpResponseRedirect('/monitor/')
else:
r = DetalleRecepcion.objects.get(id_proveedor=idp,year=year,month=month)
form = RecepcionForm(instance=r)
return render_to_response('recepcion.html',
{'form':form},
context_instance=RequestContext(request))
UPDATE
I change the function and I put all inside a function and now can I pass the arguments, but I get the error:
ReferenceError: data is not defined
http.send(data)
In firebug I can see the function pass the value to the view and the view answer the form with the info that I need, but I need to open the form not only pass the value.
Any advice.

Related

jQuery error in client post response - POST HTTP/1.1" 400

I can't figure out what is wrong with my code and I'm not really good with jQuery.
I'm trying to build HTML form will hold cars data. It's based on this form:
HTML source code is here.
Form data is sent on button click on the end back to program.
I upgraded that form with cascading manufacturer (proizvodjac in code) and car models droplist based on this code. But it's not working.
I keep receiving HTTP 400 which would mean that my POST call from client is malformed.
Here is my jQuery functions:
$(function () {
var carsdata = {"alfaromeo":["mito","156","147","giulietta","159","166","146"],"audi":["a3","a4","a6","a5","80","a1","q3","a8","q5"],"bmw":["320","116","x3","316","318","118","530","x1","520","x5","525","330","120","323","serija 1"],"chevrolet":["spark","lacetti","captiva","aveo","cruze"],"citroen":["c4","c4 grand picasso","c3","c5","c4 picasso","xsara","berlingo","c2","xsara picasso","saxo","ds5","c1"],"fiat":["brava","bravo","panda","grande punto","stilo","punto","punto evo","doblo","500","tipo","uno","coupe"],"ford":["c-max","fiesta","focus","mondeo","fusion","ka","escort"],"honda":["civic","accord","cr-v"],"hyundai":["getz","i10","i20","atos","i30","coupe","elantra","accent","santa fe","ix35","tucson"],"kia":["rio","pro_cee'd","sportage","cee'd","pride","sorento"],"mazda":["3","2","323 f","626","6","cx-5","323","premacy","5"],"mercedes":["a-klasa","c-klasa","e-klasa","b-klasa","124"],"mercedes-benz":["e-klasa","clk-klasa","c-klasa","s-klasa","190","a-klasa","b-klasa","c t-model","ml-klasa","w 124","124"],"nissan":["qashqai","x-trail","note","primera","micra","juke","almera"],"opel":["corsa","astra","zafira","meriva","vectra","insignia","mokka","tigra","combo","astra gtc","kadett"],"peugeot":["308","207","206","306","106","307","208","406","508","407","partner","3008","405"],"renault":["thalia","clio","scenic","grand scenic","kangoo","captur","megane grandtour","megane","laguna","5","megane break","twingo","modus","kadjar","megane classic","espace","megane scenic","megane coupe","megane sedan"],"seat":["toledo","leon","ibiza","altea","cordoba"],"skoda":["fabia","octavia","120","superb","felicia","rapid"],"smart":["fortwo"],"toyota":["corolla","yaris","auris","avensis","rav 4","land cruiser"],"vw":["polo","golf v","golf iv","golf vii","passat","golf vi","jetta","passat variant","caddy","sharan","tiguan","golf variant","golf ii","vento","golfplus","golf iii","bora","touran","touareg","up!"]};
var proizvodjac = $('<select id="proizvodjac"></select>');
var model = $('<select id="model"> </select>');
$.each(carsdata, function(item, key) {
proizvodjac.append('<option >' + item + '</option>');
});
$("#containerProizModel").html(proizvodjac);
$("#proizvodjac").on("change", function(e) {
var item;
var selected = $(this).val();
if (selected === "alfaromeo") {
item = carsdata[selected];
} else {
item = carsdata[selected];
}
$(model).html('');
$.each(item, function(item, key) {
model.append('<option >' + key + '</option>');
});
});
$("#containerProizModel").append(model);
$("button#predict").click(function(e){
e.preventDefault();
/*Get for variabes*/
var kilometraza = $("#kilometraza").val(), godina_proizvodnje = $("#godina_proizvodnje").val();
var snaga_motora = $("#snaga_motora").val(), vrsta_goriva = $("#vrsta_goriva").val();
/*create the JSON object*/
var data = {"kilometraza":kilometraza, "godina_proizvodnje":godina_proizvodnje, "proizvodjac":proizvodjac, "model":model, "snaga_motora":snaga_motora, "vrsta_goriva":vrsta_goriva}
/*send the ajax request*/
$.ajax({
method : "POST",
url : window.location.href + 'api',
data : $('form').serialize(),
success : function(result){
var json_result = JSON.parse(result);
var price = json_result['price'];
swal('Predviđena cijena auta je '+price+' kn', '','success')
},
error : function(){
console.log("error")
}
})
})
})
Comments and explanations are in the code.
On server side:
Server is expecting user_input dictionary which is built from variables returned by POST request. Here is how API method looks:
#app.route('/api',methods=['POST'])
def get_delay():
result=request.form
proizvodjac = result['proizvodjac']
model = result['model']
godina_proizvodnje = result['godina_proizvodnje']
snaga_motora = result['snaga_motora']
vrsta_goriva = result['vrsta_goriva']
kilometraza = result['kilometraza']
user_input = {'proizvodjac':proizvodjac,
'model':model,
'godina_proizvodnje':godina_proizvodnje,
'snaga_motora':snaga_motora,
'vrsta_goriva':vrsta_goriva,
'kilometraza':kilometraza
}
print(user_input)
a = input_to_one_hot(result)
price_pred = gbr.predict([a])[0]
price_pred = round(price_pred, 2)
return json.dumps({'price':price_pred});
Error from Google Chrome Developer Console:
which is pointing to:
EDIT 1:
I don' know how to pass proizvodjac and model to onClick function. See what happens on breakpoint:
XHR on Network tab:
HTML form is being filled with data OK only manufacturer and model are not passed to onClick:
EDIT 2:
Getting closer to solution. I've added :
var proizvodjac = $("#proizvodjac").val()
var model = $("#model").val()
as suggested and now all variables are successfully passed!
But I still get error 400 as final ajax POST call is getting stuck somwhere..
EDIT 3:
changed from
data : $('form').serialize()
to
data = data
AJAX method receives everything ok:
Still it doesn't work.
There are two main issues here:
1) you aren't getting the values from two of your fields correctly. You need to add
var proizvodjac = $("#proizvodjac").val()
var model = $("#model").val()
inside the $("button#predict").click(function(e){ function.
2) You're collecting all these values and putting them into your data variable...but then you aren't doing anything with it. Your AJAX request is configured as follows in respect of what data to send:
data : $('form').serialize()
The serialize() function automatically scoops up all the raw data from fields within your <form> tags. In your scenario, if you want to send a custom set of data (rather than just the as-is contents of the form) as per your data object, then you simply need to change this to
data: data
so it sends the information from that object in the POST request instead.

Django render template in template using AJAX

My site currently renders forms on their own page. I'm trying to get them to render inside a sidebar div tag now on my main page. However, I can't figure out how to shape the JavaScript and/or View so I get the HTML of the form template back and inserted into the div tag.
UPDATE
I'm getting the following error in the console: GET http://127.0.0.1:8000/new_trend/ 500 (Internal Server Error)
HTML (tag on the main page which I want to inject the form template into):
<div id="sidebar">
</div>
JavaScript
$(function() {
$("#new-trend").click(function(event){
alert("User wants to add new trend"); //this works
$.ajax({
type: "GET",
url:"/new_trend/",
success: function(data) {
$('#sidebar').html(data),
openNav()
}
})
});
});
VIEW
def new_indicator(request):
# if this is a POST request we need to process the form data
if request.method == "POST":
# create a form instance and populate it with data from the request:
form = IndicatorForm(request.POST)
# check whether it's valid:
if form.is_valid():
indicator = form.save(commit=False)
indicator.author = request.user
indicator.modified_date = timezone.now()
indicator.save()
return redirect('dashboard')
else:
form = IndicatorForm()
return render(request, 'mysite/sidebar_trend.html', {'form': form})
I was able to figure this out on my own. For others who come across this (myself included!), here's how I got it working.
JavaScript
There was a couple of fixes here. First you need to include the csrftoken, which yo can get through another JS function. Second, the AJAX request needs to be a POST, not a GET (not sure why, if you know please comment below). Here's the updated code snippet...
// Get cookie for CSRF token (from Django documentation)
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
};
// Load new Trend form
$(function() {
$("#new-trend").click(function(event){
var csrftoken = getCookie('csrftoken');
$.ajax({
type: "POST",
url: "/new_trend/",
data: {'csrfmiddlewaretoken': csrftoken},
success : function(data) {
$('#sidebar').html(data);
openNav()
}
})
alert("User wants to add new trend") //this works
});
});
VIEW
The second thing that needs to be corrected is the View function. First you need to render the HTML into a string, then return the string in an HttpResponse. This blog post provides a detailed explanation of why so I'm not going to go into it here. This is what the new code looks like...
#login_required
def ajax_indicator_form(request):
form = IndicatorForm()
html = render_to_string('mysite/sidebar_trend.html', {'form': form})
return HttpResponse(html)

jquery elements with django forms

I am using jquery elements that a user can drag and drop. I post the order of the elements to django using ajax.
Inside the django view I am able to work with the data that is posted from ajax.
Django views:
#this is the view where the jquery elements are being ordered by the user
def inside_exam(request):
if request.method=='POST':
form = MyForm(request.POST)
if form.is_valid():
#here I am able to retrieve the data from ajax and save it to a django model, code not shown here
return redirect('exam_results')
#the view redirected to from the inside_exam view
def exam_results(request):
#here I set the score for the exam and set the context, code not shown here
print(“all is set”)
return render(request, 'quizresults.html', context)
The print(“all is set”) is executed and I am able to print the html for quizresults.html in the browser. No errors are in the terminal window and this is shown in the terminal: "GET /exam_results/ HTTP/1.1" 200 8981.
But the same template is still shown, it is not showing the quizresults.html template. Any idea why the render(request, 'quizresults.html', context) is not working as expected?
By the way: when I use a django form without the jquery, everything works fine and the quizresults.html template is shown.
Since I want to show the user another template, but not update the current template, is ajax maybe not the correct way to send the jquery data in this case? If not, what would be a better way?
Edit, ajax code:
function dataToSend() {
{% load static %}
var node2 = document.getElementById('sortable');
var idsInOrder = $("#sortable").sortable('toArray');
console.log("the ids");
console.log(idsInOrder);
var fd = new FormData();
for(var i=0; i<idsInOrder.length; i++) {
j = i+1
fd.append('a'+j, idsInOrder[i]);
}
$.ajax({
type: 'POST',
data: fd,
cache: false,
processData: false,
contentType: false
}).done(function(data) {
//The data from the quizresults.html template is printed out here, but that template is not shown, the template in the browser is still the insidequiz.html template.
console.log("the data");
console.log(data);
});
}
window.onload = function init() {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
};
Using redirect shortcut method in Django will return a HttpResponseRedirect object back to the AJAX, which it will be processed as a 302 Found status code, which then will make another request to the redirected resource and get the content. This does not seem to be the right way to do it, even though you get the content.
You can use the method exam_results to do the other work and return the required context, which shall be used to return the HttpResponse object using render method.
Then, with the data you get, you can replace the document with the template you receive.
Solution:
# views
#this is the view where the jquery elements are being ordered by the user
def inside_exam(request):
if request.method=='POST':
form = MyForm(request.POST)
if form.is_valid():
#here I am able to retrieve the data from ajax and save it to a django model, code not shown here
context = exam_results(request)
return render(request, 'quizresults.html', context)
# method to set the score for the exam
# return context from this method
def exam_results(request):
#here I set the score for the exam and set the context, code not shown here
# build context
return context
# javascript
$.ajax({
type: 'POST',
data: fd,
cache: false,
processData: false,
contentType: false
}).done(function(data) {
//The data from the quizresults.html template is printed out here, but that template is not shown, the template in the browser is still the insidequiz.html template.
console.log("the data");
console.log(data);
// replace the page with the new template
var newDoc = document.open("text/html", "replace");
newDoc.write(data);
newDoc.close();
// update the url
window.history.pushState('', 'title', "newurl");
});
Ref: History API MDN
I figured that ajax makes things complicated when it comes to redirecting. What I ended up doing was to create an HTML form (that is hidden) and then post that form to a url using javascript. No need for ajax.
HTML code:
<form id="form1" action='{% url 'inside_exam' %}' method="post" style="display:none;">
{% csrf_token %}
</form>
<p> <button type='submit' style="visibility" class="button button-long button-primary" onclick="sendData(this);">Send</button></p>
javascript code:
function sendData() {
var idsInOrder = $("#sortable").sortable('toArray');
var form = document.getElementById('form1');
for(var i=0; i<idsInOrder.length; i++) {
j = i+1
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", 'a'+j);
hiddenField.setAttribute("value", idsInOrder[i]);
form.appendChild(hiddenField);
}
console.log("form is:");
console.log(form);
form.submit();
}

How to use HTML data from ajax call

i have a load more button on some content that is pulled from a database via ajax.
The ajax call looks like so:
// JavaScript Document
// load more builds function
$(document).ready(function(){
var pageIndex = 1;
$('#loadmorebuilds-div').click(function() {
$.ajax({
url: 'includes/loadmorebuilds.php?type=' + type + '&pageIndex=' + pageIndex,
success: function(html) {
$("#buildcontainer").append(html).waterfall('reflow');
$("#loadmorebuilds-div").stop().fadeOut();
pageIndex++;
var rowCount = MAKE THIS THE VALUE THAT IS APPENDED;
$('.testcount').html(rowCount);
if (rowCount < 18) {
$('#loadmorebuilds-div').remove();
$('.countvar').detach();
} else {
$('.countvar').detach();
}
}
});
});
});
In the appended items, is a div that contains a value of the row count for the database query that has been carried out via the above ajax call.
Normally, i would put this value into a JSON return and simply do e.g.:
rowCount = response.rowCount
However i am not using a JSON datatype but HTML.
How can i get this value from the appended div in the data and use it to set a var?
Thanks!
Use either:
val = $("#thatDiv").text();
or
val = $("#thatDiv").attr("value");
The latter of which, is if you put the value in a pseudo attribute...

Hidden input text submit with jquery

I have a javascript var that returns the value of a input text ID "ven_prod", with the value of "ven_prod" I need to make a search in my database without submiting the page.
I can't use a javascript var in the java code, so i've setted the value in a hidden input text ID "prod_hidden", but I need to submit it to get the value with the java code and make the search...How do I do it ?
<input id="ven_prod" type="text" placeHolder="Código de Barras" autofocus>
<input id="prod_hidden" type="text" value="">
<script>
$('#ven_prod').keypress(function (e)
{
if(e.keyCode==13)
{
var table = document.getElementById('tbprodutos');
var tblBody = table.tBodies[0];
var newRow = tblBody.insertRow(-1);
var prod = document.getElementById('ven_prod').value;
var qtd = document.getElementById('ven_qtd');
var barra = prod.substring(0, 12);
var num = prod.substring(14, 16);
document.getElementById('prod_hidden').value = barra;
var ref = <%=pd.getProdutosBarra(request.getParameter("prod_hidden")).getPro_referencia()%>;
OR
var ref = <%=pd.getProdutosBarra(JS VAR 'barras HERE).getPro_referencia()%>;
if(prod.length==16) {
var newCell0 = newRow.insertCell(0);
newCell0.innerHTML = '<td>'+ref+'</td>';
var newCell1 = newRow.insertCell(1);
newCell1.innerHTML = '<td>'+num+'</td>';
var newCell2 = newRow.insertCell(2);
newCell2.innerHTML = '<td>'+qtd.value+'</td>';
var newCell3 = newRow.insertCell(3);
newCell3.innerHTML = '<td>R$ '+valor+'</td>';
var newCell4 = newRow.insertCell(4);
newCell4.innerHTML = '<td>'+barra+'</td>';
document.getElementById('ref').value = '6755';
document.getElementById('imgsrc').src = './?acao=Img&pro_id=1';
document.getElementById('valortotal').value = 'Testando novo valor';
document.getElementById('ven_prod').value = '';
document.getElementById('ven_qtd').value = '1';
} else {
document.getElementById('ven_prod').value = '';
document.getElementById('ven_qtd').value = '1';
alert("Código de barras inválido!");
}
return false;
}
});
</script>
you can make ajax call using jQuery as follows. will submit your form data as well along with hidden elements.
var form = jQuery("#YourFormID");
jQuery.ajax({
type: "POST",
url: form.attr("action"),
data: form.serialize(), // serializes the form's elements.
success: function(data) {
console.log(data);
}
});
value of a input text named "pro_barras"
Are you sure? Look at this:
<input type="hidden" id="pro_barras">
its not the name of the input, its the ID. You can try using this:
<input type="hidden" name="pro_barras">
And now, you can use $.ajax to send the request to a new page, where you will request the data from the database. And then you'll write the response, and take it back on the first page.
What it will do depends on how you use it. I will try to ask you to simply use serialize() method by jQuery API, this will let you to create a simple URL param with the data from the form, use it as:
$.ajax({
var data = $('#formid').serialize(); // serialize the form..
url: "link/to/file.cshtml",
data: data,
success: function (datares) {
$('#resultid').html(datares); // write the result in the element
}
})
If you want to get only the value from that field you can use
var data = $('input[name=pro_barras]').val();
without submiting the page.
Your page will have to be submitted when you click on input type="submit" button. To prevent that you can use
$('#idofsubmitbutton').click(function () {
return false; // stop execution and stay on page..
}
Then the ajax will continue, other method is to remove the input type="submit" and use <button></button> which won't cause any submission.
get the value with the java code
This isn't java :) Its JavaScript, they are totally different. :)
a) You can use like that:
$("#pro_barras").bind("change paste keyup", function() {
//$('.someClass').submit();
$('#it_is_form_id').submit(); // it call form's submit function
});
The piece of code detected when input text change. To more info see also here If you want to customize form submit function
$('#it_is_form_id').bind("submit", function(){
//alert("submit");
// make here simple ajax query
return false; //<-- it is used so that default submit function doesn't work after above code.
});
Don't forget, all code will be inside
<script>
$(function() {
// your code must be here
});
</script>
b) If you don't want to use form, you can do like that:
<script>
$(function() {
$("#pro_barras").bind("change paste keyup", function() {
var text = $("#pro_barras").val();
$.ajax({
type: "POST",
url: "yourUrl",
data: text,
success: function(res){
console.log(res);
},
error: function(err){
console.log(err);
}
});
});
});
</script>
Making simple ajax query:
Using Jquery post method
https://stackoverflow.com/a/8567149/1746258
Pass entire form as data in jQuery Ajax function
You could also add a custom attribute to your input element (in Jquery):
<input type='text' id='pro_barras' customattr='myCustomInfo'/>
<script>
var customValue = $('#pro_barras').attr('mycustomvar');
alert(customValue);
</script>
Fiddle

Categories

Resources