In the example code below, Ajax calls (in the page.html) the same Python function (page()) which Django used to create the page in the first place. It gets a HTTPResponse object, which contains the page as it should look after the Ajax call. But the possibly modified page in the HTTPResponse object is not applied to modify the actual page. Is it possible to do so, or am I thinking something not doable?
page.html
$( document ).ready(function() {
$.ajax({
url: "",
success: function(data) {
//Here to make the webpage determined by this page.html
//to look like how it is rendered in the HTTPResponse object "data"
}
})
})
views.py
def page(request):
//...
return render(request, page.html)
urls.py
urlpatterns = [
path('', views.page, name="page"),
]
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?
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'
)
I'm trying to have Django to run a function when I tell it based off a JavaScript button. How do I accomplish this? Where do I write the Django function?
JavaScript in main.html:
function mainFunction(){
alert("Beginning API Main Function");
$.ajax({
type: 'POST',
url: 'livestream/postdata/',
success: function(){alert('DONE!');},
error:function(){alert('ERROR!');},
});
alert("ENDING API MAIN FUNCTION");
}
Urls.py:
url(r'^postdata$', 'livestream.views.postdata', name='postdata')
Views.py:
def postdata(request):
r = ...api... (I know that the api works)
print(r.text)
When I run the function 'mainFunction()' I get the two alerts and then another that says 'ERROR'. Why is this?
Set up a route in your urls.py file
url(r'^action/$', 'yourproject.views.action', name='action')
In your views.py file, you would create that action.
def action(request):
# do your magic!
Then, when someone interacts with that button, do an ajax call that hits the URL at /action.
You add a listener to the button which makes an ajax call when fired. In your view.py you handle the response for that ajax call.
#HieuNguyen
Thank You for answering my question. It was through chat, so I'll write down, what worked.
in ajax need a '/' before lifestream. /livestream/postdata/
url(r'^postdata/$', 'livestream.views.postdata', name='postdata')
in views.py
before function I needed #csrf_exempt
return HttpResponse(r)
I have a following code that is part of the _form.html.erb code. Basically I have a form in which I have a observe_field function where on change, it will set fields' values without refreshing the page. Following is my html code:
<script type="text/javascript">
// When DOM loads, init the page.
$(function() {
// Executes a callback detecting changes with a frequency of 1 second
$("#id_element_placeholder").observe_field(1, function( ) {
$.ajax({
type: "GET",
dataType: "json",
url: "/students/get/" + this.value,
success: function(data){
$('#last_name').attr('value', data.student.last_name);
$('#building').attr('value', data.student.building);
$('#room').attr('value', data.student.room);
}
});
});
});
</script>
Problem here is that I'm exposing lot of my code in javascript. Is there a better way to do it without exposing code in javascript?
Here is what my controller looks like:
def get
#student = Student.find(params[:id])
respond_to do |format|
format.html
format.json { render :json => #student }
end
end
Basically I get an id in a form and from there I have to get the corresponding object and update the fields on the page.
Assuming your design requires you to make AJAX calls to query student info by id, then you need to expose a URL for the call. If you don't want to expose a JSON data structure, you could return a chunk of HTML (instead of JSON), and replace the contents of the container of all of the controls you mention above.