I'm trying to implement a simple code testing server. The client will submit their code on the webpage and we will run it with two test cases (which could take several minutes) and we'll post the results. The page will be simple with a submission form and an output box.
My problem is with updating the output box. I'm looking for the simplest way to implement the output box so that we show results as we run different test cases.
I tried googling for solutions and I found some like socket.io but my experience with ajax and socket.io or even js is very limited so I'm looking for the simplest way to do this.
In case you are looking for code to auto-update a field in HTML here is the code which you could use. The setInterval in JavaScript schedules get_log view to be pulled every 1 second for result of get_log_from_disk method.
urls.py
url(r'^get_log/$', 'myapp.views.get_log', name='get_log'),
url(r'^submit/$', 'myapp.views.submit', name='submit'),
views.py
def submit(request):
## Handle POST
## Your code comes here
return render(request, 'submit.html', {})
def get_log_from_disk():
## Your code comes here
return "Test 1 OK; Test 2 OK"
def get_log(request):
results = get_log_from_disk()
return HttpResponse(results)
in submit.html add
<head>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
[<div id="output_box"></div>]
<script>
$(document).ready(function() {
$.ajaxSetup({ cache: false }); // This part addresses an IE bug. without it, IE will only load the first number and will never refresh
var my_refresh = setInterval(function() {
$('#output_box').load('/get_log/');
}, 1000); // the "1000"
});
</script>
</body>
You could modify "$('#output_box').load('/get_log/');" to test for status of request and when "204 No Content" is returned you can remove the function (clearInterval(my_refresh );)
see Stop setInterval call in JavaScript
Modify get_log view to return "204 No Content" when there is no more content to be sent.
Here I have uploaded working version
https://github.com/lukaszszajkowski/Django-jQuery-Example-update-part-of-page/tree/master
Some reading
Auto-refreshing div with jQuery - setTimeout or another method?
This could be what you are looking for:
var ajaxForm = function() {
$.ajax({
type: 'POST',
contentType: 'application/json',
dataType: 'json',
url: '/path/to/django/controller',
// The data sent to the Django view in JSON format
data: JSON.stringify({
formField: $('#body').val()
}),
success: function (data) {
$('#output-box').html(data);
}
});
}
$('#form').on('submit', function (e) {
e.preventDefault();
ajaxForm();
});
The implementation of a Django controller can be something like:
import json
from django.http import HttpResponse
def ajax_view(request):
if request.method == 'POST':
request_data = json.load(request.raw_post_data)
# do something
response_data = {}
response_data['result'] = 'Failed'
response_data['message'] = 'Your test not ended well'
return HttpResponse(
json.dumps(response_data),
content_type='application/json'
)
Related
I have a python script that takes in some data and manipulates it. However i need it to run on the client side inside the javascript to process some data and refresh the view.
The python file that manipulates data works well as I have tested it inside the IDLE shell
DataManipulation.py
class ModifyData(object):
#Bunch of functions to manipulate data
below is the function used to render the view with url '.../test' which also works perfectly.
views.py
def test(request):
template = 'app/test.html'
file = 'documents/Sample.csv' #File to be loaded
args = {'test': file }
return render(request, template, args)
After loading this page, i use a javascript library that displays the data on the page in a table, the user can then manipulate the data like multiply a column by 3, but where I am stuck is how to take my DataManipulation.py file to modify the data and updates the page with the updated column on a button click
Since executing python client side is not an option, you have two options.
re-write ModifyData in Javascript and use it client side.
When a user does something like multiply a column by 3:
Use client side JS to make an ajax request to the server
Have your server call ModifyData, and then return the data to the client
have client update view with new data
I would recommend porting your python code to JS, but if that isn't possible #2 will always work. How you implement will just depend on how you manage data in the client.
I think you should pass the data into template, and then use javascript to manipulate the data, after that you can use ajax to update your page without refresh, example:
<!--html-->
<button onclick="deleteUser({{ request.user.pk }})">Submit</button>
<!---->
function deleteUser(userid) {
var post_data = {
'userid': userid,
}
$.ajax({
type: "POST",
url: "/deleteuser",// the view function to post
data: post_data,
contentType: 'application/json;charset=UTF-8',
success: function(result) {
// do something after post
...
}
});
}
the view function:
# url(r'^/deleteuser$', views.delete_user)
def delete_user(request):
if request.method == 'POST':
# do something
userid = request.POST.get('userid')
user = User.objects.get(pk=userid)
# dict contain response data
response_data = {...}
# return response
return HttpResponse(json.dumps(response_data),content_type='application/json')
There are a lot of gaps in my knowledge, so I may be trying to solve this the wrong way. The goal is to use this Google Maps JavaScript API to autocomplete and parse address input, and save the results in a model.
I couldn't find a way to pass variables from JS directly to view.py, so now the plan is to have the JS fill a hidden field as suggested by a previous unsolved question.
Could the fields generated by a ModelForm be used for this? If not, how should the form be created so that the JS fills in the fields, the fields are hidden and unchangeable by users, and it makes use of csrf_token?
This is all I have so far. There are a bunch of input fields that get filled automatically by the JS. The form|crispy generated by ModelForm doesn't get filled, even though the id is the same (field names in models.py are the same as Google's naming scheme). I don't understand how the last paragraph of the JS works, that's likely where I'm stuck.
Update:
The following code is not giving a POST, why?
<!-- language: lang-js -->
$.ajax({
type: 'POST',
url: 'http://localhost:8000/place/new',
dataType: 'json',
data: {
csrfmiddlewaretoken: '{{ csrf_token }}',
address: 'test'
},
success: function (response, textStatus, error) {
console.log('SUCCESS')
},
error: function (request, textStatus, error) {
console.log('error')
console.log(place)
}
});
<!-- end snippet -->
<!-- language: lang-python -->
def placenew(request):
if request.method == 'POST':
test = request.POST.get('address')
response_data = {}
print (test)
print ("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")
return render(request, 'app/placenew.html', {'key':key})
else:
print ("not POST")
return render(request, 'app/placenew.html', {'key':key})
<!-- end snippet -->
If you wanted to pass variables from the JS to django then you could look at posting an ajax request to your view and providing whatever data you want in the data attribute.
For example, I'm in the middle of doing exactly this using Knockout JS so I have this ajax request;
$.ajax({
url: URLS.design,
method: 'POST',
data: {
data: ko.mapping.toJSON(structure_data)
},
success: function (response, textStatus, error) {
console.log('SUCCESS')
},
error: function (request, textStatus, error) {
console.log('error')
}
});
You could get the field values, variables or whatever else you wanted and pass them in the data attribute of $.ajax.
Alternatively you could setup fields in your ModelForm with the HiddenInput() widget so your javascript can populate them, without your user worrying about them. Then if they were populated correctly, you could just post the form & your data would be sent to the view.
To read up on Ajax, this looks like a great article; https://realpython.com/blog/python/django-and-ajax-form-submissions/
Essentially the url attribute would just be somewhere you've got your view setup like /myapp/myview/ and then in your view it's very similar to how you'd handle any normal POST request. For example, I'm currently doing this with the above bit of Javascript when it hits my view;
def get_forms(self, forms):
data = None
if self.request.method in ('POST', 'PUT'):
if self.request.is_ajax():
_json = self.request.POST.get('data')
data = json.loads(_json)
else:
data = self.request.POST
Update
Well first of all when you're defining your URL, make sure you include a trailing slash or when it hits Django it'll get redirected. So you'll want url: '/place/new/'.
Also, your response from the server should return JSON if it's received an AJAX request. So you might do something like;
def placenew(request):
if request.method == 'POST':
test = request.POST.get('address')
response_data = {}
if request.is_ajax():
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
)
return render(
request, 'app/placenew.html', {'key':key}
)
else:
print ("not POST")
return render(request, 'app/placenew.html', {'key':key})
Also, I'm assuming you've followed that tutorial and have your ajax call defined within a function which you trigger somehow when your form is submitted?
Okay here's my problem.
I have an html page that has a javascript variable initialized in it.
<html>
<script>
MyVaribale = "Random Data";
</script>
<!-- Then I include an external js file to handle the processes in this html file -->
<script type="text/javascript" language="javascript" src="/scripts/some_random_script.js"></script>
</html>
Now, inside that script. I used the MyVaribalevarible in one of the ajax request there, like this :
$(document).ready(function() {
$.ajax(
url : '/some/random/url',
data : { MyVariable : MyVaribale }
etc ...
);
});
So, on page load, that ajax code is executed immediately.
In the url specified above, i checked for the existence of MyVaribale, then flag an error that it is a required value if it doesn't exist.
Backend code like this (in Perl):
my $MyVariable = trim_param('MyVariable'); # trim_param() is a function that gets the passed data from ajax.
if ( $MyVariable ) { # Test if it exists
# Display something
}
else {
# Flag an error, which is my problem
}
Now I am sure that in the html page, that variable is always populated (yes 100% sure). But I always get flag errors that that value doesn't exist in my backend code (url above).
So question,
Does ajax have some issue with document.ready, maybe it executes before the variable has finished assigning a value? Any idea why this happens? Because sometimes my ajax request is successful, sometimes it's not
Thanks
The syntax of your ajax call is not correct. Have a look here and then try this code (note the addition of {, } and ,):
MyVaribale = "Random Data";
$(document).ready(function() {
$.ajax({
url: '/some/random/url',
data : { myVariable : MyVaribale }
});
});
Did not you try out some complete ajax calls? Like this.Sometimes no need to use JSON.stringify for MyVariable.
$.ajax({
url: "/some/random/url",
type: 'POST',
dataType: 'json',
data: JSON.stringify(MyVaribale),
contentType: 'application/json',
mimeType: 'application/json'
}).done(function(data) {
}).fail(function(error) {
}).always(function(){
});
In my webpy app I have a function:
def POST (self):
signal = web.input()['signal']
if signal == 'next':
errMessage = self.cinstall.testConnection()
print signal
print errMessage
return errMessage
According to the python console it works correctly; it receives and returns strings as I expect it to.
In a template I have a script like this:
<script src="/static/jquery-1.7.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$$(function() {
var value = $$('#continue').attr('value');
$$("#continue").click(function(){
jQuery.ajax({
type: "POST",
data: {signal : value},
success: function(html) {
jQuery('#errmessage').html(html).hide().fadeIn(1500);
},
});
});
});
</script>
I know that the request is successful, because if I put an alert in the success handler it works well, but the function jQuery('#errmessage').html(html).hide().fadeIn(1500); doesn't execute. I have a <p> tag with id=errmessage in my template.
So I have several questions:
Why it doesn't work?
Can I isolate the data recieved from POST in JS for further iterations and if statements?
Can I put if statements inside the jQuery.ajax success function?
Unfortunately, jQuery API gives limited info about success().
This is my ajax function:
function ajax_call(call_method,data_to_send) {
logger("function ajax_call. var data_to_send: ");
logger(data_to_send);
$('.clickable save_button').hide()
$.ajax({
type: 'POST',
url: call_method,
data: data_to_send,
success: function(data){
logger("data returned to page after ajax call: ");
logger(data);
$('.error_msg').html("Successfully saved record to database.");
$('.error_msg').fadeIn('slow');
setTimeout("$('.error_msg').fadeOut('slow');",5000); // 5 secs to give user enough time to read
$('.clickable save_button').show()
response_dispatcher(data); // This should contain object type at least
},
failure: function(){
$('.error_msg').html("There was an error while saving this information. Please try again. " +
"If the error persists, please contact us using the contact form.");
$('.error_msg').show;
$('.clickable save_button').show()
},
dataType: 'json'
});
}
And, this is the data sent to my method on the backend:
{
'display_order':"3",
'goal':"dummy goal",
'id':-1,
'object_type':"goal"
}
I've verified within my application that this same data is received.
Here is my Django view method:
#login_required
def update_goal_view(request):
if request.method == 'POST' and request.is_ajax:
# Example data sent from AJAX Request
#qd = {u'display_order': [u'23'], u'object_type': [u'goal'], u'goal': [u'dummy goal'], u'id': [u'-1']}
qd = request.POST
goal = qd.get('goal','')
display_order = qd.get('display_order',99999)
id = int(qd.get('id',''))
object_type = qd.get('object_type','')
# For now, just return something to test populating data to the page
id = '100'
goal = 'goal returned'
object_type = object_type
data = {'id':id,'goal':goal,'object_type':object_type}
return HttpResponse(data,mimetype="application/json")
In Firebug, I see this after the ajax call:
POST http://127.0.0.1/xml/update_goal 200 OK 12ms
The issue is, when that it appears that my success callback is never called... I say that because as you can see from above, I there should be a message written to my logger but there isn't one. I know my logger works because of all the other messages outside of the callback that do get written to my logger.
I don't think Django does automatic serialization for dictionaries. You'll have to serialize them to JSON by hand.
import simplejson
# ...
return HttpResponse(simplejson.dumps(data), mimetype="application/json")
You don't show the code that triggers the ajax_call function. If it's as part of the onclick event for a submit button, or the onsubmit event for a form, the usual cause is that you've forgotten to prevent the form from submitting normally - so the page refreshes and the Ajax call is lost.
Use event.preventDefault() in your event handler to fix this.