Django, Ajax- HttpResponse does not send json - ajax

Django 1.7.2/ python 3.4
this code is about 'like'.
if user click the 'like' button, ajax calls 'pushLike'.
if the user has liked the article before(saved inside Mysql), delete the row on table(DB).
or if the user is not liking the article, create a row and insert it on the table(DB).
after that, count how many like has beed clicked on that article.
I would like to pass the likeCnt(count) to ajax, and write it on the button.
The likeCnt has the right value(I checked it on the server mysql table).
The button color does change(white to blue, and vise versa), but the text does not change.
It seems like json does not pass to ajax. I tried passing data by 'text' type and it did worked, but i want it by json.
I've tried simplejson, json, mimetype, content_type on HttpResponse.
please help me.
view
#login_required
def pushLike(request):
pk = request.GET['writing_id']
try:
la = LikeArticles.objects.get(user = User.objects.get(username=request.user.username), article_id=pk)
if(la.is_like()):
la.delete()
likeCnt = LikeArticles.objects.filter(article_id=pk).count()
FreeBoards.objects.filter(id=pk).update(like = likeCnt)
else: #Never happens
la.like = True
la.save()
likeCnt = LikeArticles.objects.filter(article_id=pk).count()
FreeBoards.objects.filter(id=pk).update(like = likeCnt)
except ObjectDoesNotExist:
la = LikeArticles(user = User.objects.get(username=request.user.username),
article = FreeBoards.objects.get(id=pk),
like = True,
)
la.save()
likeCnt = LikeArticles.objects.filter(article_id=pk).count()
FreeBoards.objects.filter(id=pk).update(like = likeCnt)
data = {'likeCnt': likeCnt}
# return render(request, url, context)
return HttpResponse(simplejson.dumps(data), mimetype='application/javascript')
javascript
<script type="text/javascript">
$(document).ready(function(){
$('#btn-like').click(function(){
var e = $('#btn-like').css('background-color');
$.ajax({
url : '/sle/freeboards/pushLike/',
data : {'writing_id':{{writing_id}},
},
dataType : "json",
success:function(data){
alert(data.likeCnt);
if(e == 'rgb(59, 89, 152)') {
$('#btn-like').css('background-color', '#ffffff').css('color', '#000000');
$('#btn-like').text(data.likeCnt);
} else {
$('#btn-like').css('background-color', '#3b5998').css('color', '#ffffff');
$('#btn-like').text(data.likeCnt);
}
},
failure: function(data){
alert('fail!!')
}
});
});
});
</script>

you'll want to be sure to set the proper mimetype in your HttpResponse
#login_required
def pushLike(request):
...
# return json -- !!not javascript!!
return HttpResponse(simplejson.dumps(...), mimetype="application/json")
--or--
#login_required
def pushLike(request):
...
# return json -- !!not javascript!!
return JsonResponse({"your": "context dictionary"})
If that doesn't work, have you tried parsing the json with your Jquery code?
ie:
$.ajax({
...
success: function(data){
var response = $.parseJSON(data);
...
}
});
javascript might actually receiving bytes back from whatever you are serving your django app with... so instead of getting JSON back, you're actually getting string that looks like JSON. http://api.jquery.com/jquery.parsejson/

Related

Retrieve post variable sent via Ajax in Django

I'm processing a table of banking/statement entries that have been exported from another system via a CSV file. They are imported into a view and checked for duplicates before being presented to the user in a HTML table for final review.
Once checked they are sent via AJAX to the server so they can be added into a Django model. Everything is working OK including CSRF but I cannot access the POSTed variable although I can see it!
Unfortunately making a hidden form isn't viable as there are 80+ rows to process.
My Javascript looks like:
$.ajax({
type: 'POST',
url: '......./ajax/handleImports/',
data: entriesObj,
success: function (data) {
if (data.response && data.response) {
console.log("Update was successful");
console.log(data.entries)
} else { ... }
},
error: function() { ... }
where entriesObj is
var entriesObj = JSON.stringify({ "newentries": newEntries });
console.log(entriesObj)
and when dumped to console.log looks like:
{"newentries":[{"Include":"","Upload ID":"0","Date":"2019-01-09", ... }
Now in view.py when I return the whole request.POST object as data.entries using
context['entries'] = request.POST
return JsonResponse(context)
I get
{"{"newentries":[{"Include":"","Upload ID":"0","Date":"2019-01-09", ... }
but if I try and retrieve newentries with:
entries = request.POST.get('newentries', None)
context['entries'] = entries
return JsonResponse(context)
the console.log(data.entries) will output null?
How am I supposed to access the POSTed entriesObj?
The data is JSON, you need to get the value from request.body and parse it.
data = json.loads(request.body)
entries = data.get('newentries')

Django - Making an Ajax request

Im having a hard time figuring out how to integrate this ajax request into my view. I'm still learning how to integrate django with ajax requests.
My first question would be: Does the ajax request need to have its own dedicated URL?
In my case I am trying to call it on a button to preform a filter(Preforms a query dependent on what is selected in the template). I have implemented this using just django but it needs to make new request everytime the user preforms a filter which I know is not efficient.
I wrote the most basic function using JQuery to make sure the communication is there. Whenever the user changed the option in the select box it would print the value to the console. As you will see below in the view, I would to call the ajax request inside this view function, if this is possible or the correct way of doing it.
JQuery - Updated
$("#temp").change( function(event) {
var filtered = $(this).val();
console.log($(this).val());
$.ajax({
url : "http://127.0.0.1:8000/req/ajax/",
type : "GET",
data : {
'filtered': filtered
},
dataType: 'json',
success: function(data){
console.log(data)
},
error: function(xhr, errmsg, err){
console.log("error")
console.log(error_data)
}
});
Views.py
def pending_action(request):
requisition_status = ['All', 'Created', 'For Assistance', 'Assistance Complete', 'Assistance Rejected']
FA_status = RequisitionStatus.objects.get(status='For Assistance')
current_status = 'All'
status_list = []
all_status = RequisitionStatus.objects.all()
status_list = [status.status for status in all_status]
# This is where I am handling the filtering currently
if request.GET.get('Filter') in status_list:
user_req_lines_incomplete = RequisitionLine.objects.filter(Q(parent_req__username=request.user) & Q(status__status=request.GET.get('Filter')))
current_status = request.GET.get('Filter')
else:
user_req_lines_incomplete = RequisitionLine.objects.filter(parent_req__username=request.user).exclude(status__status='Completed')
user_reqs = Requisition.objects.filter(par_req_line__in=user_req_lines_incomplete).annotate(aggregated_price=Sum('par_req_line__total_price'),
header_status=Max('par_req_line__status__rating'))
return render(request, 'req/pending_action.html', { 'user_reqs':user_reqs,
'user_req_lines_incomplete':user_req_lines_incomplete,
'requisition_status':requisition_status,
'current_status':current_status,
'FA_status':FA_status})
def filter_status(request):
status = request.GET.get('Filter')
data = {
'filtered': RequisitionLine.objects.filter(Q(parent_req__username=request.user) & Q(status__status=status)),
'current_status': status
}
return JsonResponse(data)
Urls.py
path('pending/', views.pending_action, name='pending_action')
First: you have to divide your template to unchangeable part and the part that you want to modify with your filter.
Second: for your goal you can use render_to_string. See the followning link https://docs.djangoproject.com/en/2.1/topics/templates/#usage
code example (views.py):
cont = {
'request': request, #important key-value
'your_models_instances': your_models_instances
}
html = render_to_string('your_filter_template.html', cont)
return_dict = {'html': html}
return JsonResponse(return_dict)
In your js file you need to determine relative url "{% url 'name in yours url file'%}"
And in success you need to add next line:
success: function(data){
$(".filter-block").html(data.html);
}
i hope it will help you! Good luck!

render a view to the client with json request

I come back with this with new question and more clear description, I hope, because I made a lot of changes but i havent found a working solution yet. To start from the beginning I have a view which whenever I push a button I want to return the rendered view from another view.
#csrf_exempt
def main(request):
menu_beer = Food.objects.filter(category=4)
menu_crepe = Food.objects.filter(category=2)
menu_club = Food.objects.filter(category=1)
menu_spaggetti = Food.objects.filter(category=8)
menu_burgers = Food.objects.filter(category=11)
menu_hotdog = Food.objects.filter(category=1)
menu_salads = Food.objects.filter(category=7)
menu_toast = Food.objects.filter(category=3)
menu_dessert = Food.objects.filter(category=6)
menu_coffee = Food.objects.filter(category=9)
menu_soda = Food.objects.filter(category=5)
menu_food = Food.objects.filter(category=1)
menu_offer = Offer.objects.all()
obj={}
print "request ajax------------------------"
if request.is_ajax():
print "inside ajax\/\/\//\/\/\/"
sItem=request.GET.get('itemId')
print "GET itemId="+sItem
if sItem is not None:
getobject=Food.objects.get(id=int(sItem))
print getobject
obj['id']=getobject.id
obj['title']=getobject.title
print "{}= "+str(obj)
return HttpResponse(json.dumps(obj), content_type="application/json")
else:
print "ERRRRRRR"
return render(request,'main.html',{'view_title':"Menu",
'menu_crepe':menu_crepe,
'menu_club':menu_club,
'menu_spaghetti':menu_spaggetti,
'menu_burgers':menu_burgers,
'menu_hotdog':menu_hotdog,
'menu_salads':menu_salads,
'menu_toast':menu_toast,
'menu_dessert':menu_dessert,
'menu_coffee':menu_coffee,
'menu_soda':menu_soda,
'menu_beer':menu_beer,
'menu_offer':menu_offer,
})
def profile(request):
return render(request,'profile.html')
#csrf_exempt
def order(request):
obj={}
print "request ajax------------------------"
if request.GET:
print "POST"
sItem=request.GET.get('itemId')
print "GET2 itemId="+sItem
if sItem is not None:
getobject=Food.objects.get(id=int(sItem))
print getobject
obj['id']=getobject.id
obj['title']=getobject.title
print "post2= "+str(obj)
return render(request,'order.html',{"obj":obj})
else:
print "ER"
return render_to_response("order.html",{'obj':obj})
js is like:
$(document).ready( function(){
$(".orderbtn").click(function(){
p=$(this).prop("id");
$.ajax({
type:"GET",
url:"order/",
data:{"itemId":p
//'csrfmiddlewaretoken': $("{% csrf_token %}")
},
success: function(data){
$('#selected').html("data.title");
}
});
});
});
All the code and the files are https://github.com/b10n1k/foodspot69.git
and the part of main.html where should display the data between div with id="menu_display".
<div id="selected" class="selected"></div >
So, I am not sure how must handle each view in this case. Any suggestion what I am doing wrong?
I found the solution on this and I post it without details to help others. In success function I added two parameters and now it looks:
success: function(data){
$('#selected').html(data, textStatus, jqXHR);
}
I hope someone can give more details about because I dont know why they are required.

not getting response from ajax call in codeigniter

I am trying to check if the user name is available for use using ajax and codeigniter. I have problem to get the response from the codeingniter controller in my js. file but without success.
Here is the controller function, relevant to the question:
if ($username == 0) {
$this->output->set_output(json_encode(array("r" => true)));
} else {
$this->output->set_output(json_encode(array("r" => false, "error" => "Username already exits")));
}
Rest assured that I do get 1 if username already exists in thedatabase and 0 if it does not exist.
I have the following js.file
// list all variables used here...
var
regform = $('#reg-form'),
memberusername = $('#memberusername'),
memberpassword = $('#memberpassword'),
memberemail = $('#memberemail'),
memberconfirmpassword = $('#memberconfirmpassword');
regform.submit(function(e) {
e.preventDefault();
console.log("I am on the beggining here"); // this is displayed in console
var memberusername = $(this).find("#memberusername").val();
var memberemail = $(this).find("#memberemail").val();
var memberpassword = $(this).find("#memberpassword").val();
var url = $(this).attr("action");
$.ajax({
type: "POST",
url: $(this).attr("action"),
dataType: "json",
data: {memberusername: memberusername, memberemail: memberemail, memberpassword: memberpassword},
cache: false,
success: function(output) {
console.log('I am inside...'); // this is never displayed in console...
console.log(r); // is never shonw in console
console.log(output); is also never displayed in console
$.each(output, function(index, value) {
//process your data by index, in example
});
}
});
return false;
})
Can anyone help me to get the username value of r in the ajax, so I can take appropriate action?
Cheers
Basically, you're saying that the success handler is never called - meaning that the request had an error in some way. You should add an error handler and maybe even a complete handler. This will at least show you what's going on with the request. (someone else mentioned about using Chrome Dev Tools -- YES, do that!)
As far as the parse error. Your request is expecting json data, but your data must not be returned as json (it's formatted as json, but without a content type header, the browser just treats it as text). Try changing your php code to this:
if ($username == 0) {
$this->output->set_content_type('application/json')->set_output(json_encode(array("r" => true)));
} else {
$this->output->set_content_type('application/json')->set_output(json_encode(array("r" => false, "error" => "Username already exits")));
}

Grails - Fails to submit base64 img

I need to make ajax submit to submit some data include a base64 string of the image, which is render from canvas.
When submit I look in the network panel of Chrome inspector and everything look fine, in "form data" it list all the data that I want to submit.
But in Grails I cannot get the data, there is nothing in the params, just the controller name and action name. Thus everything I get with simple params.dataName is null.
I guess there is something with the size of the post request, but I'm not so sure as I have done this before without ajax.
This is my code for upload with jquery ajax:
var imgBase64String = canvas.toDataURL("image/png");
imgBase64String = imgBase64String .replace('data:image/png;base64,', '');
var submitData = $(form).serializeArray();
submitData.push({name: "webImage", value: imgBase64String })
$.ajax({
type: 'POST',
url: '${createLink(action: 'myAction')}',
data: submitData,
dataType: "html",
success: function(data){//Success code},
});
UPDATE
My code on the server side, it fails at the simple step to retrieve params data:
def myAction= {
def paramData = params
log.info "paramData: " + paramData
def url = params.url
def email = params.email
def webImage = params.webImage
log.info "param: url = " + url
log.info "param: email = " + email
log.info "param: webImage = " + webImage
//Other implement code
}
And the output:
2012-10-08 16:31:28,988 [http-bio-8080-exec-5] INFO myController - paramData: [action:myAction, controller:myController]
2012-10-08 16:31:28,989 [http-bio-8080-exec-5] INFO myController - param: url = null
2012-10-08 16:31:28,989 [http-bio-8080-exec-5] INFO myController - param: email = null
2012-10-08 16:31:28,989 [http-bio-8080-exec-5] INFO myController - param: webImage = null
The size of the base64 image I'm trying to submit is 1998720, don't know if this matter.
Many thanks.
I believe you can simply pass canvas.toDataURL("image/png") into the data field in the $.ajax() method. Also use $.post() instead of $.ajax(). So your code should look like this in the js file:
$.post('/image/getCanvasImage', //this is your url
{
img : canvas.toDataURL('image/jpeg'),
email : email
}, function(data){
//whatever you wanna do with the returned data
}
);
Then in your action, import import sun.misc.BASE64Decoder package and you can write this code to save the canvas image:
def file = params.img.toString().substring((params.img.toString().indexOf(",")+1),params.img.toString().size())
byte[] decodedBytes = new BASE64Decoder().decodeBuffer(file)
def image = new File("mySavedImage.jpg")
image.setBytes(decodedBytes)
Should work!

Resources