I currently have a javascript variable called myVariableToSend that contains a single string and I need to send to my views where I can make raw SQL queries to gather corresponding data from the database and bring it back to my javascript. Here is what I have:
Javascript:
function scriptFunction(myVariableToSend){
$.getJSON("http://127.0.0.1:8000/getData/", myVariableToSend, function(serverdata){
window.alert(serverdata);
});
Views.py:
def getData(request):
some_data = request.GET(myVariableToSend)
cursor = connection.cursor()
cursor.execute("SELECT Car_ID FROM cars WHERE Carname = %s ", [some_data])
row = cursor.fetchall()
return JsonResponse(row, safe = False)
Urls.py:
url(r'^admin/', include(admin.site.urls)),
url(r'^$', startpage),
url(r'^getData/$', getData ),
I don't think my server side script(views.py) is working because when I run my server, I get a http500 error. Any help would be appreciated. Thank you.
UPDATE:
I have found that when I comment out my entire Views.py and only put
def getData(request):
return JsonResponse({"hello":"World"}, safe = False)
I get no problems and the AJAX request works. But when I have my original getData, it doesn't work. When I add this line in my views.py:
some_data = request.GET(myVariableToSend)
, I get an error and the data isn't displayed
If u want to send ur variables to function in view, u can capture it with url, like this:
$.getJSON('http://127.0.0.1:8000/getData/' + myVariableToSend +'/', function (serverdata) { //do ur work}
Then in urls.py you have:
url(r'getData/(?P<my_var>\w+)/$', views.get_data, name='get_data')
Then views.py:
def get_data(request, my_var):
#do ur work here
Answering the original question:
Your server is failing probably because bad syntax in views.py
some_data = request.GET(myVariableToSend)
myVariableToSend is undefined here. So you should get it like this:
some_data = request.GET['myVariableToSend']
Besides the original question:
You'll get a lot of headaches if you try to set up your django app like this.You can query your database way easier if you use django's ORM. Read about it here.
Also, if you want to send the data in your models to your javascript code, you can save yourself lots of time by using a framework like Django REST Framework.
Related
Okay, so I have been going at this for a while and it doesn't seem like I am getting anywhere. I am running a Django app with Nginx and uwsgi. I have an http.post and I am trying to even read the items which I keep getting errors for.
This is what my JS code looks like :
$scope.receipt_pay_update = function(items)
{
response = confirm("Do you want to continue with the changes?");
if(!response){
return;
}
var data = {
'items': items,
'time_now': moment().format("YYYY-MM-DD")
};
items.showmessage = true;
console.log(data)
$http.post("/foodhub/dashboard/receipt_pay_modal_update", data,{
data: JSON
}).
success(function(data,status,headers,config){
$scope.alertclass = 'alert-success';
$scope.save_message_farmer = "Succcessfully update payment"
console.log("SAVED!")
}).
error(function(data,status,headers,config){
$scope.alertclass = 'alert-danger';
$scope.save_message_farmer= "Failed to update inventory, please try again"
})
}
This is what my views.py looks like:
#login_required
def receipt_pay_modal_update(request):
import sys
reload(sys)
sys.setdefaultencoding('utf8')
data = json.loads(request.body)['items']
print data
rec = ReceiverActions.objets.get(identifier = data[0]['identifier'])
rec['paid_check'] = data[0]['paid_status']
rec['date_paid'] = data[0]['paid_date']
rec.save()
return HttpResponse(status=status.HTTP_200_OK)
I got an error of unable to decode JSON. So I tried data = request.body[0] which also didn't work.
Is there any other way I could be testing small changes on my server without having to do the Git push, Git Pull, Python -m compileall ., etc? The reason I ask is because I was taught to do it this way by practice and I feel there is a better way.
Where can I check my print data?
Any help would be highly appreciated.
Turns out the data I was getting was not JSON appropriate. I went back and changed the request to send data as a json and it worked perfectly.
I have a website built using the django framework that takes in an input csv folder to do some data processing. I would like to use a html text box as a console log to let the users know that the data processing is underway. The data processing is done using a python function. It is possible for me to change/add text inputs into the text box at certain intervals using my python function?
Sorry if i am not specific enough with my question, still learning how to use these tools!
Edit - Thanks for all the help though, but I am still quite new at this and there are lots of things that I do not really understand. Here is an example of my python function, not sure if it helps
def query_result(request, job_id):
info_dict = request.session['info_dict']
machines = lt.trace_machine(inputFile.LOT.tolist())
return render(request, 'tools/result.html', {'dict': json.dumps(info_dict),
'job_id': job_id})
Actually my main objective is to let the user know that the data processing has started and that the site is working. I was thinking maybe I could display an output log in a html textbox to achieve this purpose.
No cannot do that because you already at server side therefor you cannot touch anything in html page.
You can have 2 ways to do that:
You can make a interval function to call to server and ask the progress and update the progress like you want at callback function.
You can open a socket connection in your server & browser to instantly update.
While it is impossible for the server (Django) to directly update the client (browser), you can you JavaScript to make the request, and Django can return a StreamingHttpResponse. As each part of the response is received, you can update the textbox using JavaScript.
Here is a sample with pseudo code
def process_csv_request(request):
csv_file = get_csv_file(requests)
return StreamingHttpResponse(process_file(csv_file))
def process_file(csv_file):
for row in csv_file:
yield progress
actual_processing(row)
return "Done"
Alternatively you could write the process to the db or some cache, and call an API that returns the progress repeatedly from the frontend
You can achieve this with websockets using Django Channels.
Here's a sample consumer:
class Consumer(WebsocketConsumer):
def connect(self):
self.group_name = self.scope['user']
print(self.group_name) # use this for debugging not sure what the scope returns
# Join group
async_to_sync(self.channel_layer.group_add)(
self.group_name,
self.channel_name
)
self.accept()
def disconnect(self, close_code):
# Leave group
async_to_sync(self.channel_layer.group_discard)(
self.group_name,
self.channel_name
)
def update_html(self, event):
status = event['status']
# Send message to WebSocket
self.send(text_data=json.dumps({
'status': status
}))
Running through the Channels 2.0 tutorial you will learn that by putting some javascript on your page, each time it loads it will connect you to a websocket consumer. On connect() the consumer adds the user to a group. This group name is used by your csv processing function to send a message to the browser of any users connected to that group (in this case just one user) and update the html on your page.
def send_update(channel_layer, group_name, message):
async_to_sync(channel_layer.group_send)(
group_name,
{
'type': 'update_html',
'status': message
}
)
def process_csv(file):
channel_layer = get_channel_layer()
group_name = get_user_name() # function to get same group name as in connect()
with open(file) as f:
reader=csv.reader(f)
send_update(channel_layer, group_name, 'Opened file')
for row in reader:
send_update(channel_layer, group_name, 'Processing Row#: %s' % row)
You would include javascript on your page as outlined in the Channels documentation then have an extra onmessage function fro updating the html:
var WebSocket = new ReconnectiongWebSocket(...);
WebSocket.onmessage = function(e) {
var data = JSON.parse(e.data);
$('#htmlToReplace').html(data['status']);
}
and python/cherrypy server
#cherrypy.tools.json_out()
#cherrypy.tools.json_in()
def get_data(self):
cherrypy.response.headers['Content-Type'] = 'application/json'
datas = {"ABCDEF"}
return datas
but I get a Internal Server Error (500), where is my mistake?
I get work to post data to server, but with getting data is my problem..
One problem is in your fifth line of your second code block. Change
datas = {"ABCDEF"}
to something like
datas = { "somedata" : "ABCDEF"}
And if this is all of your cherrypy server code, you're not exposing your route. Then you have to add the
#cherrypy.expose
annotation. You can consult the docs for this as well.
Your datas variable is a Python set, and those are not directly serialisable to JSON. Perhaps you meant to create a dictionary or list?
I want to build a stock website with Django, and I found a Javascript library (tickp) to make charts, but I don't know Javascript, nor do I know how to read json data in a Django template. I use this code to retrieve the stock data from Yahoo Finance.
I put these .py and .js in my folder, and my views like this:
from stock.stockretriever import StockRetriever
def stockretriever(request,number):
data = StockRetriever().get_historical_info('YHOO')
return HttpResponse(simplejson.dumps(data),mimetype='application/json')
But I don't know how I should write the template, can somebody tell me?
thanks.
You have two options:
render a template with data included
dynamically fetch data from the server
If you go for 1. you could add something like this to your template:
<script type="text/javascript">
var my_data = {{ json_plot_data }};
</script>
The template includes also the javascript code that generates the plots from the data. The view function would include the data fetching and return a context object like so:
def my_stock_plot_view(request, number):
# get stock data
json_data = simplejson.dumps(data)
django.shortcuts.render(request, 'template.html', {'json_plot_data':json_data})
If you go for 2. you would need to use something like jQuery.ajax to dynamically load json data using an ajax request. That request would invoke your view, in the jQuery.ajax call you specify that the request returns JSON which automatically makes the data available as an object to Javascript. In the jQuery.ajax success handler you would pass the data to your plot function.
I don't have these libraries installed, but based on the readme of the tickp library, you'll need the following data: [date, open, high, low, close and optionally volume]. The get_historical_info function returns the columns [Date, Open, High, Low, Close, Volume, AdjClose]. The mismatch here is the AdjClose, so you'd need to strip that from the data you get from the StockRetriever:
from django.shortcuts import render
from stock.stockretriever import StockRetriever
def stockretriever(request, number):
data = StockRetriever().get_historical_info('YHOO')
# Assuming data is returned as a list of lists
new_data = [d[:-1] for d in data]
return render(request, 'stock.html', { 'data': simplejson.dumps(new_data) })
Following along with the readme, you need something along the following lines in your template:
<html>
<head><script src="tickp.js"></script><script src="stats.js"></script></head>
<body onload='plot = window.tickp("#chart"); plot.read({{ data }}); plot.plot();'>
<div id="chart"></div>
</body>
</html>
Note that I've cut some corners with respect to possible Ajax calls or proper formatting and usage, but it should give you something to get started with. When you're missing something, please update your question with the specific issues you're having.
Problem Overview:
I am creating a Django-based client with the intent of returning data from a web service. The goal of this project is to return data to the user from the web service based on the values selected by the user in a form. Upon the form submit, a query string is generated, sent to the web service and the page data is returned as a string. Currently, that data is displayed to the user in the browser. I want to provide the functionality that would allow the user to click a button and download the data.
Question:
How could I return the data to the user when they click a button in their browser for download? How do I make different options of the same data available (i.e. application/json, or text/csv)?
Current (not-working) Implementation:
I am attempting, and failing, to do the following:
views.py
Returning a render_to_response object of my template. To the template I pass the form, and the data in it's various forms.
def view(request):
#Do stuff, get data as string
#Get data into needed formats (see utils.py)
jsonData = jsonToJsonFile(dataString, fileName)
return render_to_response('template.html', {'someForm' : aForm,
'regularData' : stringData,
'jsonData' : jsonData...})
utils.py
Contains functions to take the data as a string and return response objects. This part I am unsure if I am doing correctly. I call these functions in the view to get jsonData (and csvData) into their proper formats from the original data string.
def jsonToJsonFile(dataString, fileName):
#Get the data as json
theData = json.dumps(dataString)
#Prepare to return a json file
response = HttpResponse(theData, mimetype = 'application/json')
response['Content-Disposition'] = 'attachment; filename=' + str(fileName) + '.json'
#return the response
return response
template.html
I am currently passing the responses into the template. This is where I am really lost, and have not yet begun to find a good solution. I expect I will need to use javascript to return the variables (jsonData and csvData) to the user when the button is clicked. I have attempted the use of the onclick action of the anchor class, and then using javascript to return the django variable of the response - but this really isn't working.
<li class = 'button'>
<a href = "#dataButtons" onclick = "javaScript:alert('test');">
TEST
</a>
</li>
<li class = 'button'>
<a href = "#dataButtons" onclick = "javaScript: var a = '{{ jsonData }}'; return a;">
JSON
</a>
</li>
I put the test part in there to, well, test whether or no the alert would work. It does. However, when I click the button for the json data, nothing happens.
Am I approaching this completely wrong? Or is there something small that I am missing?
Solution:
After looking at the problem a little further and talking to a colleague about it, it seems as though my problem lies in trying to pass the response object to the javascript. For those interested, I solved the problem with a little careful re-routing of the data.
views.py
In my views.py I added a couple lines of code in my main view that would set variables of two extra views (one for csv one for json) to the response objects holding the data. These two extra views would then be called when their respective buttons were pressed, returning the httpresponse and prompting the user for download.
#MAIN VIEW FUNCTION
def view(request):
#Do stuff, get data as string
#Get data into needed formats
jsonData = jsonToJsonFile(dataString, fileName)
#Set values to external view ****NEW PART****
returnJSON.jsonData = jsonData
#Render main template
return render_to_response('mainTemplate.html', {'someForm' : aForm,
'regularData' : dataString})
#SECONDARY VIEW TO RETURN JSON DATA TO USER ****NEW PART****
def returnJSON(request):
#Simply return the response
return returnJSON.jsonData
template.html
Then, when the button is pressed by the user, the anchor is linked via the url to the secondary django view that will present the download option to the user.
<li class = 'button'>
<a href = "{% url client.views.returnJSON %}">
JSON
</a>
</li>
urls.py
Lastly, I just pointed my url patterns to the view.
urlpatterns = patterns('',
(r'^somesite/$', views.view),
(r'^somesite/json$', views.returnJSON),
)
So far, this method has worked great for me! If anyone has any other suggestions, or a better method, I would certainly be open to hear it.
I think you need to change your javascript to make it start a file download - see this question & answer:
starting file download with JavaScript