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!
Related
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!
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/
before starting let me say that I am new to dojo and this is my first project in dojo:
when I am trying to send json data from rest client (some chrome ext) it working for me,I mean to say that my spring mvc part is working, but when i am trying to send the same json from dojo code I am getting http 400 exception
my dojo code:
postCreate : function() {
this.inherited(arguments);
var form = dom.byId("contactSubmit");
on(form, "click", function(evt) {
var box0 = registry.byId("inputEmail");
var box1 = registry.byId("inputName");
var box3 = registry.byId("message");
alert("values are: " + box0.get("value"));
jsonData = {"email":"some#gmail.com","inputName":"some name","message":"some msg"};
request.post("/pool/conta", {
data: jsonData,
handleAs: "json",
headers: {
"Content-Type": "application/json;charset=utf-8",
"Accept": "application/json"
}
}).then(function(text){
alert("values are send"+text);
});
});
}
the jason data that I am sending from rest client is which is working:
{"email":"some#gmail.com","inputName":"some name","message":"some msg"}
my spring mvc method is below:
#RequestMapping(value="/conta", method = RequestMethod.POST)
public #ResponseBody Contact getShopInJSON(#RequestBody Contact contact2) {
Contact contact = new Contact();
contact.setEmail("pro#gmail.com");
contact.setInputName("pro");
contact.setMessage("msg");
System.out.println("***********************"+contact2.getEmail());
return contact;
}
pool is name of application
The json data as passed in post request requires string to be crypted with "\" so that the javascript can handle the double codes as is within string(double quoted string).
Thus, the line
jsonData = {"email":"some#gmail.com","inputName":"some name","message":"some msg"};
would work if written as below
jsonData = " {\"email\":\"some#gmail.com\",\"inputName\":\"some name\",\"message\":\"some msg\"} " ;
Its working now, I have used toJson from dojo/_base/json" utility before passing it to request.post
I am trying to have an authentication set-up similar to that of StackOverflow, where the normal browsing is never affected unless there are some privileged actions which requires authentication (Do not bother users until then).
It should be as "Log In" if not logged in or "UserName" if logged in.
The relevant part of base.html (from fallr.net) (extended by index.html) looks like :
<script type="text/javascript">
//<![CDATA[
$(document).ready(function(){
var methods = {
forms : function(){
var login = function(){
var user = $(this).children('form').children('input[type="text"]').val();
var pass = $(this).children('form').children('input[type="password"]').val();
var dataString = '&username=' + $('input[name=username]').val() + '&password=' + $('input[name=password]').val();
if(user.length < 1 || pass.length < 1){
alert('Invalid!\nPlease fill all required forms');
} else {
alert('username: '+user+'\npassword: '+pass);
$.ajax({
type: "POST",
url: "/login",
dataType: "html",
data: {
username : user,
password : pass,
csrfmiddlewaretoken : '{{ csrf_token }}'
},
success: function(json){alert (json.server_response);},
error: function(xhr,errmsg,err) { alert(xhr.status + ": " + xhr.responseText); }
});
$.fallr('hide');
return false;
}
}
$.fallr('show', {
icon : 'secure',
width : '320px',
content : '<h4>Sign in</h4>'
+ '<form>'
+ '<input name="username" placeholder="username" type="text"/'+'>'
+ '<input name="password" placeholder="password" type="password"/'+'>'
+ '</form>',
buttons : {
button1 : {text: 'Submit', onclick: login},
button4 : {text: 'Cancel'}
}
});
}
};
//button trigger
$('a[href^="#fallr-"]').click(function(){
var id = $(this).attr('href').substring(7);
methods[id].apply(this,[this]);
return false;
});
// syntax highlighter
hljs.tabReplace = ' ';
hljs.initHighlightingOnLoad();
});
//]]>
</script>
The urls.py looks like :
from django.conf.urls import patterns, include, url
#from triplanner.views import *
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', main_page),
url(r'^login$',ajax_login),
url(r'^login/$','django.contrib.auth.views.login'),
url(r'^logout/$', logout_page),
# our application page
url(r'^account/',include('tripapp.urls')),
)
Also, '^login/$' is the previous implementation for learning which I want to replace with Ajax login.
And my views.py:
# -*- coding: utf-8 -*-
from django.contrib.auth import logout
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.contrib.auth import authenticate, login
#from django.http import HttpResponse
from django.template import RequestContext
#from django.utils import simplejson
def main_page(request):
return render_to_response('index.html', context_instance=RequestContext(request))
def logout_page(request):
"""
Log users out and redirect them to the main page
"""
logout(request)
return HttpResponseRedirect('/')
def ajax_login(request):
"""
This view logs a user in using the POST data.
"""
if request.method == 'POST':
print request.POST['username']
username = request.POST['username']
password = request.POST['password']
print username
print password
user = authenticate(username=username, password=password)
if (not user is None) and (user.is_active):
login(request, user)
response_dict = {}
response_dict.update({'server_response': username})
#return HttpResponse(simplejson.dumps(response_dict),mimetype='applicaion/javascript')
return render_to_response('index.html',{'username' : user}, context_instance=RequestContext(request))
# Set Session Expiry to 0 if user clicks "Remember Me"
#if not request.POST.get('rem', None):
# request.session.set_expiry(0)
#data = username
else:
return render_to_response('index.html', context_instance=RequestContext(request))
I am getting a 403 Error like "[20/Aug/2013 00:29:20] "POST / HTTP/1.1" 403 2294"
UPDATE NUMBER 1:
With the changed urls.py, views.py and javascript I am able to get a 200 response, but it gives alert window saying undefined and alerting me "Prevent this page from creatng dialog boxes"
The approach I use is to have a Tastypie api layer and require authentication for the APIs. If the API call fails because of authentication, the client can request the user to log-in via the ajax login method.
You can log-in a user via ajax using this gist
So, it looks like your current problem is with this: alert (json.server_response);. You may want to look into changing your $.ajax dataType parameter to json.
To quote the docs:
The type of data that you're expecting back from the server. If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string). The available types (and the result passed as the first argument to your success callback) are:...
"html": Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.
"json": Evaluates the response as JSON and returns a JavaScript object. The JSON data is parsed in a strict manner; any malformed JSON is rejected and a parse error is thrown. As of jQuery 1.9, an empty response is also rejected; the server should return a response of null or {} instead. (See json.org for more information on proper JSON formatting.)
I am submitting a for using dojo's xhrpost. My app runs on ruby on rails. In the controller I am performing a redirect. I store the redirected URL the response headers. I access the redirected URL on the client and then load the redirected URL on the client. The following is the code.
In the view, performing ajax submit using dojo.xhrpost
function () {
var form = dojo.byId("form_id");
dojo.connect(form, "onsubmit", function(event){
// Stop the submit event since we want to control form submission.
dojo.stopEvent(event);
var xhrArgs = {
form: dojo.byId("form_id"),
handleAs: "text",
load: function(data, ioargs){
//getting redirected url from response header
var new_url = ioargs.xhr.getResponseHeader("new_url");
//redirecting to the url
document.location.href = new_url;
},
error: function(response){
//handling error
}
}
//submitting for to action1 of controller
var deferred = dojo.xhrPost(xhrArgs);
});
}
Code in controller
def action1
new_url = url_for(:controller=>"controller", :action => "action2")
#passing the new URL as parameter in the redirection
redirect_to :action2, :new_url => new_url
end
def action2
#getting the new url from the params and saving it in respone header so that it can be accesses in client
response.headers["new_url"] = params[:new_url]
end
This worked fine on my local host. But when I put it on my server its failing.
I am getting the ioargs.xhr.status as "0". data is " ". Though the form is getting saved response is empty and no response headers are getting set.
Please Help.
I had to modify the controller a bit.
def action1
if request.xhr?
render :json => new_url.to_json
else
#follow normal redirection
redirect_to :action2
end
Also in the ajax call
var xhrArgs = {
form: dojo.byId("form_id"),
handleAs: "json",
load: function(data, ioargs){
//getting redirected url from data
document.location.href = data;
},
error: function(response){
//handling error
}
Basically I found out returning the entire HTML page as response in not the right way.
Only the URL should be returned in the response and redirection should be done from the View,