How to get and access JSON data from ajax in django view? - json

I am trying to send dynamically created JSON data from my template using ajax call to the view. I am able to generate and pass the JSON data via ajax call but unable to read the same in the view. I read lots of articles and stackoverflow post regarding this but nothing worked for this simple task. Below is my Ajax call:
$(document).ready(function() {
$('#applybtn').click(function(){
var selectedpackages = [];
{% for package in packages %}
if($("input[name=package{{forloop.counter}}]").is(':checked')){
type = $("input[name=package{{forloop.counter}}]:checked").attr('id');
var Obj = {}
Obj['pkgid'] = {{package.id}};
Obj['type'] = type;
selectedpackages.push(Obj);
}
{% endfor %}
var mystring = JSON.stringify(selectedpackages);
$.ajax({
url:"/ApplyCode/",
type:"GET",
data:mystring,
dataType: "json",
contentType: "application/json",
success: function(data){
alert(data);
}
});
});
});
In above given code, you can ignore the for loop part as it is just looping through some packages and checking that which package is selected by users on that page and accordingly generating a dictionary to pass as JSON object. Also, I checked the data generated in mystring variable (using alert(mystring);) before sending it to view and it was having the desired data.
Below is the code for my view:
import json
def applycode(request):
context=RequestContext(request)
pkgid=""
if request.method=='GET':
selectedpackages = json.loads(request.body)
else:
pass
return HttpResponse(selectedpackages)
I am sure I am missing something over here while getting the JSON data in "selectedpackages" variable. I tried lots of other ways as well but nothing worked. Here I just want to get the data and than wants to access each element of the same. Any help is appreciated.

request.body will not have anything in it if you do a GET request, which will put everything in the URL itself. You need to change your AJAX call to do a POST:
$.ajax({
// ...
type:"POST",
// ...
});
and then modify your view code accordingly:
if request.method == 'POST':
selectedpackages = json.loads(request.body)

Related

TypeError: Object of type Reporter is not JSON serializable

I am trying to add the reporter with ajax but it is not working properly. When I send json data with {'reporter':reporter.name} then it creates the obj in the database successfully but I am not being able to display this newly created obj in the select option. I have to refresh to see this object in the select option. Then I tried sending the object instance as a JsonResponse by dumping with json.dumps(obj) but I am getting this error serializable error.
I have to create the reporter object and display in the select option without page refresh. How can I do it ? What's wrong here in my approach ?
view
class AddReporterView(View):
def post(self, request):
name = request.POST.get('name')
reporter = Reporter.objects.create(name=name)
data = {
'reporter': json.dumps(reporter)
}
return JsonResponse(data)
Scripts
$(document).on('submit','#target-category-form',function(e) {
e.preventDefault();
var form = $(this);
$.ajax({
url: form.attr("action"),
data: {
name:$('#name').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
},
type: 'POST',
dataType:'json',
success: handleFormSuccess,
});
});
function handleFormSuccess(data){
$("#id-categories").html(data);
$('#modalOpen').modal('toggle');
console.log(data);
}
I want to display the created data here in this html select element
<select class="form-control" name="reporter" multiple="multiple" id="id-categories">
{% for reporter in reporters %}
<option value="{{reporter.pk}}">{{reporter.name}}</option>
{% endfor %}
</select>
To convert an instance to a dictionary, you can use model_to_dict.
from django.forms.models import model_to_dict
reporter = Reporter.objects.first()
data = {'reporter': model_to_dict(reporter)}
By default, the serialization is done implicitly in the JsonResponse using json.dumps so you don't need to bother with it
# glimpse of source code.
class JsonResponse(HttpResponse):
def __init__(self, data, encoder=DjangoJSONEncoder, **kwargs):
...
data = json.dumps(data, cls=encoder, **json_dumps_params)
super().__init__(content=data, **kwargs)
EDIT
// add this to your success callback
// you can create option either in python or javascript.
success: function(data){
// on success, dynamically append the select drop down list
$('#id-categories').append(`<option value =${data.reporter.id}> ${data.reporter.name}</option>`)
}

Django - How to render html and return a json at the same time

I have a view which populate a json object, and then, at the end of the same view I would render an html page, but also return the final json.
probably this is not relevant but the json would be for example something like this:
{
"embedToken": "dasfgjasdàgjasdàgasdàgèe-AveryLongToken",
"embedUrl": "https://app.powerbi.com/let's_go_to_the_lake",
"reportId": "e615-sfash-9746"
}
the line I'm not able to fix (tried all day with all alternatives methods) is the following:
return render(request, "home.html", jsn)
my url.py is simple as follow:
urlpatterns = [
path('', HomePageView, name='home'),
]
I currently get the following error:
context must be a dict rather than str.
But I encountered all different kinds of errors on the way without succeeding to reach the desired result(rendering the html and returning the json at the same time). So my doubt is that I'm taking the wrong approach at the basics, should I change road?
I would like to try to convert the json into a dictionary, and then maybe convert it back in a json in JavaScript
I have also tried to split my requests, by rendering the html as a Django view, and performing the function call from JavaScript ajax request as follow:
function handler1(){
// there are many other methods like $.get $.getJSON
$.ajax({
type: 'GET',
dataType: 'json',
url: "http://piedpiper.com/api/callers"
}).then(function(result) {
// do something with the result
});
}
But I ended up by understanding that in this way I must create the URL api/callers which will be available/reachable to everybody, which I cannot do, because of the user session. only the logged in user must see the json data
You need to add the proper arguments on render. Here is the docs for render function in Django
Here is a sample code of a view
def post_detail(request, slug=None):
instance = get_object_or_404(Post, slug=slug)
share_string = quote_plus(instance.content)
context = {
"title": instance.title,
"instance": instance,
"share_string": share_string,
}
return render(request, "post_detail.html", context)

How to JSON parse using form.errors.as_json() in Django return JsonResponse(data)

In Django, I tried using form.errors.as_json() to get all form errors and here is sample json data strings.
{"password2":[{"message": "This password is too short. It must
contain at least 8 characters.","code":"password_too_short"}]}
I wanted to loop and get all under "message" key in json so I can use it to notify the user after ajax call.
Thanks
Anyways, I just resolved my issue and just wanted to share what I did.
views.py
if form.is_valid():
...
else:
# Extract form.errors
errMsg= None
errMsg = [(k, v[0]) for k, v in form.errors.items()]
return JsonResponse(errMsg)
Ajax Event
$.ajax({
method: "POST",
url: '\your_url_here',
data: $form.serialize(),
cache: false,
dataType: "json",
beforeSend: function(){
//Start displaying button's working animation
//Do some button or loading animation here...
}
},
success: function(jResults)
{
//This line is to remove field name display
var strErr = jResults + ''; //make json object as string
strErr = strErr.split(",").pop();
alert(strErr);
}
});
Hope this help to anyone out there facing similar issue. By the way, I'm using Django 2.0 and Python 3.6+
Thanks
MinedBP
The correct answer should be:
return HttpReponse(form.errors.as_json(), status=400).
In the AJAX call you can get the content doing:
`$.post("{% url 'your_url'%}", your_payload).done(function(data) {
do_something();
}).fail(function(xhr){
// Here you can get the form's errors and iterate over them.
xhr.responseText();
});`
You are sending a 200 HTTP response, that it is wrong, you should return a 400 HTTP response (Bad request), like Django do without AJAX forms.

Parse JSON returned from NODE.js

I’m using jQuery to make an AJAX call to Node.js to get some JSON. The JSON is actually “built” in a Python child_process called by Node. I see that the JSON is being passed back to the browser, but I can’t seem to parse it—-although I can parse JSONP from YQL queries.
The web page making the call is on the same server as Node, so I don’t believe I need JSONP in this case.
Here is the code:
index.html (snippet)
function getData() {
$.ajax({
url: 'http://127.0.0.1:3000',
dataType: 'json',
success: function(data) {
$("#results").html(data);
alert(data.engineURL); // alerts: undefined
}
});
}
server.js
function run(callBack) {
var spawn = require('child_process').spawn,
child = spawn('python',['test.py']);
var resp = '';
child.stdout.on('data', function(data) {
resp = data.toString();
});
child.on('close', function() {
callBack(resp);
});
}
http.createServer(function(request, response) {
run(function(data) {
response.writeHead(200, {
'Content-Type':
'application/json',
'Access-Control-Allow-Origin' : '*' });
response.write(JSON.stringify(data));
response.end();
});
}).listen(PORT, HOST);
test.py
import json
print json.dumps({'engineName' : 'Google', 'engineURL' : 'http://www.google.com'})
After the AJAX call comes back, I execute the following:
$("#results").html(data);
and it prints the following on the web page:
{“engineURL": "http://www.google.com", "engineName": "Google"}
However, when I try and parse the JSON as follows:
alert(data.engineURL);
I get undefined. I’m almost thinking that I’m not actually passing a JSON Object back, but I’m not sure.
Could anyone advise if I’m doing something wrong building the JSON in Python, passing the JSON back from Node, or simply not parsing the JSON correctly on the web page?
Thanks.
I’m almost thinking that I’m not actually passing a JSON Object back, but I’m not sure.
Yes, the ajax response is a string. To get an object, you have to parse that JSON string into an object. There are two ways to do that:
data = $.parseJSON(data);
Or, the recommended approach, specify dataType: 'json' in your $.ajax call. This way jQuery will implicitly call $.parseJSON on the response before passing it to the callback. Also, if you're using $.get, you can replace it with $.getJSON.
Also:
child.stdout.on('data', function(data) {
resp = data.toString();
// ^ should be +=
});
The data event's callback receives chunks of data, you should concatenate it with what you've already received. You probably haven't had problems with that yet because your JSON is small and comes in a single chunk most of the time, but do not rely on it, do the proper concatenation to be sure that your data contains all the chunks and not just the last one.

Parsing json request in flask 0.9

(I am a complete beginner when it comes to any back-end development so I apologise if any terms are used wrong)
I have some javascript controlling a canvas game and I have a prolog planner which can solve the game. I am now trying to connect the two and have set up a flask server which can successfully call prolog, get the correct plan and send it back to the javascript. I am really struggling with getting the right inputs from the javascript.
Javascript:
var state = {
state : "[stone(s1),active(s1), stone(s2), in(app2,s2), unlocked(app2)]"
}
stone2.on('click',function(){
$.ajax({
type: 'POST',
contentType: 'application/json',
data: state,
dataType: 'json',
url:'http://localhost:5000/next_move',
success:function(data, textStatus, jqXHR){
console.log(data);
alert(JSON.stringify(state)); //making sure I sent the right thing
}
});
});
Flask server
//variables I use in the query at the moment
state = "[stone(s1),active(s1), stone(s2), in(app2,s2), unlocked(app2)]"
goal = "[in(app1,s1),in(app1,s2)]"
#app.route('/next_move', methods=['POST'])
def get_next_step():
own_state = request.json
r = own_state['state']
output = subprocess.check_output(['sicstus','-l','luger.pl','--goal','go('+state+','+goal+').'])
//I would like to use the string I got from my browser here
stripped = output.split('\n')
return jsonify({"plan": stripped})
//the correct plan is returned
I have seen the other questions regarding this, in fact the attempt I posted is from flask request.json order, but I keep getting 400 (BAD REQUEST). I'm guessing flask changed since then? I know it sends the json correctly because if I don't try to touch it I get the success message in my browser, so it is purely my inability to access its fields or to find any examples.
What you're sending through POST is not JSON. It's just a set of key value pairs and as such you should just send it through as that. And get it out using request.form.
In your case I would also not use jQuery's $.ajax and use $.post instead.
Here is the code:
stone2.on('click',function(){
$.post('http://localhost:5000/next_move',
state,
function(data) {
console.log(data);
alert(JSON.stringify(state));
}
);
#app.route('/next_move', methods=['POST'])
def get_next_step():
own_state = request.form
r = own_state['state']
print r
return jsonify({"plan": "something"})