I am trying to pass an object file (3d object) from a view to a html template using Ajax.
Here is the basic code in the view:
def guiMesh(request):
if request.method == 'POST':
if request.is_ajax():
obj = pywavefront.Wavefront( "test.obj")
context = {'meshObj': obj}
return render(request, 'template.html', context)
here is the code the template
$.ajax({
url : '', // the endpoint,commonly same url
type : "POST", // http method
data : { csrfmiddlewaretoken: csrftoken, cooVertex: cooVertex },
success : function(dataObj) {
console.log("dataObj " + dataObj.size)
})
The view side seems working as it does not give any error, but the template side seems not receiving the file correctly. Where am I doing wrong?
Thank you very much for your help!
Related
According to the documentation of django all-auth , it supports logging in through AJAX requests.When I make a normal post request to "accounts/login/" ,content type of the response header is "text/html".
But when I make a ajax call it is "application/json".
I am unable to figure what I am doing wrong, I have tried changing the contentType and dataType in ajax call but it gives a 400 Bad request error.
I have not modified any URL or view of the default Django all-auth app.
I am including the JavaScript code here -
<script type="text/javascript">
var $button = $('#login_button');
$button.on('click',function(){
var data = {"csrfmiddlewaretoken" : document.getElementsByName('csrfmiddlewaretoken')[0].value,
"login": $('#id_login').val(),
"password": $('#id_password').val(),
"remember": $('#id_remember').val() };
var temp = {'X-CSRFToken': document.getElementsByName('csrfmiddlewaretoken'[0].value };
$.post({
url : "{% url 'account_login' %}",
headers: temp,
type: "POST",
data : data,
contentType: "application/x-www-form-urlencoded",
dataType: "text",
success : function(data) {
// console.log(data);
},
});
});
</script>
it works for me, try:
$.post("{% url 'account_login' %}", {
"csrfmiddlewaretoken" : document.getElementsByName('csrfmiddlewaretoken')[0].value,
"login": $('#id_login').val(),
"password": $('#id_password').val(),
"remember": $('#id_remember').val()
},
function (data, status) {
// console.log(data);
});
I had similar issue and for me worked this solution (not a nice way but worked):
- in adapter.py you can see if form is not valid, status 400 and i have also changed the data
def ajax_response(self, request, response, redirect_to=None, form=None):
data = {}
status = response.status_code
if redirect_to:
status = 200
data['location'] = redirect_to
if form:
if form.is_valid():
status = 200
else:
status = 200
data['form_errors'] = form._errors
if hasattr(response, 'render'):
response.render()
data = response.content
return HttpResponse(json.dumps(data),
status=status,
content_type='application/json')
Here is how I used AJAX with vanilla JavaScript to login to django-allauth.
The django-allauth AJAX response does not include form errors, so I created a new class-based view based on Adam Starrh's solution:
from django.http import JsonResponse
from allauth.account.views import LoginView
class AjaxLoginView(LoginView):
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
response = self.form_valid(form)
return JsonResponse({'loggedIn': True})
else:
return JsonResponse({'loggedIn': False, 'errors': form.errors})
In urls.py I added a path to this view:
path('login-with-ajax/', AjaxLoginView.as_view(), name='loginWithAjax')
The function that makes the AJAX request does the following:
Create a new form with FormData() and add the login and password.
Encode the form with a helper method.
Use XMLHttpRequest() to post the form, using content type "application/x-www-form-urlencoded".
Here is the method I used:
loginWithAjax(submittedEmail,submittedPassword){
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
let form = new FormData()
form.set('login', submittedEmail)
form.set('password', submittedPassword)
xhr.open('POST', '/accounts/login-with-ajax/')
xhr.setRequestHeader('Content-Type', "application/x-www-form-urlencoded")
xhr.setRequestHeader("X-CSRFToken", this.getCookie("csrftoken"))
xhr.onload = () => {
if (xhr.status === 200) { //received an ajax response from view
let ajaxResponse = {
loggedIn: false,
error: ''
}
let viewResponse = JSON.parse(xhr.response)
ajaxResponse.loggedIn = viewResponse.loggedIn
if (!ajaxResponse.loggedIn){
ajaxResponse.error = viewResponse.errors.__all__[0]
}
resolve(ajaxResponse)
} else { //did not receive an ajax response from view
reject(xhr.status)
}
}
xhr.send(this.urlencodeFormData(form))
})
}
I used the method provided by cuixiping to encode the form:
urlencodeFormData(fd){
var s = '';
function encode(s){ return encodeURIComponent(s).replace(/%20/g,'+'); }
for(var pair of fd.entries()){
if(typeof pair[1]=='string'){
s += (s?'&':'') + encode(pair[0])+'='+encode(pair[1]);
}
}
return s;
}
I hope this saves someone some time in the future.
I am trying to figure out how I can make an ajax request (with jquery) from my template in order to execute a view on a button click. I don't want to redirect to another page. I just need to execute the code in the view.
This is my on button click event:
$(document.body).on("click", "#download_xls",function(e) {
selected_country = ($("#button-countries").val())
selected_subareas = $('#_all_values').val();
id = "?country=" + selected_country + "&" + "regions=" + selected_subareas
whole_url = "{% url 'test_download' %}" + id
$("#download_xls").attr("href", whole_url)
});
As I pass the values in my URL, I don't even need to pass some parameters through the ajax request. I just need to execute the code in the view.
The view is something like this:
def test_download(request):
print(request.GET.get('country'))
print(request.GET.get('regions'))
fileContent = "Your name is %s"
res = HttpResponse(fileContent)
res['Content-Disposition'] = 'attachment; filename=yourname.txt'
return res
EDITED
I have added the ajax GET request in my template as:
whole_url = "{% url 'test_download' %}"+id
$.ajax({
type: "GET",
url: whole_url,
success: function(data) {
alert('sd')
},
error: function(data) {
alert('error')
},
});
I get an error cause there is no corresponding template for this view. I think I need to add something in the urls.py file.
I read here that I need to modify urls.py as:
url(r'^link-to-fun1$', views.fun1),
But its not clear to me what should be the link-to-fun1.
I tried:
url(r'^create$', 'test_download', name='test_downlad'),
But gives an error: No Reverse Match.
You could use TemplateView add to your url and use JQuery to do something, like this:
views.py
class ajax_view(TemplateView):
def get(self, request, *args, **kwargs):
id_value = request.GET['id']
value = Model.objects.filter(id=id)
data = serializers.serialize('json', value, fields=('fieldone'))
return HttpResponse(data, content_type='application/json')
urls.py
url(r'^ajax/$', ajax_view.as_view()),
JQuery
$.ajax({
data: { 'id': id },
url: '/ajax/',
type: 'get',
success: function (data) {
// Do something with the data
}
})
That's in general how you can use Ajax with Django, the important is the use of TemplateView
I'm not able to display queryset while using ajax
here is my views.py:
if request.user.is_authenticated():
productid = request.GET.get('productId')
print productid
if request.is_ajax():
try:
queryset= StoreProduct.objects.get_size(productid)
except:
queryset= None
data = {
"queryset" : queryset
}
return JsonResponse(data)
Here is my ajax script:
<script type="text/javascript">
function getStoreView(event, productId) {
event.preventDefault();
var data = {
productId : productId
}
$.ajax({
type: "GET",
url: "{% url 'storeView' user=store.user %}",
data: data,
success: function(data) {
console.log(data.queryset)
},
error: function(response, error) {
alert(error);
}
});
};
</script>
What should I do to solve the problem above?
Thanks in advance
If you look at the error message from Django, you will see it complaining that the queryset is not JSON serializable. For ajax requests, you can see the response using your web browser's development tools when DEBUG=True.
The first thing to do is to use values(), which returns a queryset containing dictionaries for each instance in the queryset. Secondly, you need to coerce the queryset into a list.
queryset = StoreProduct.objects.get_size(productid)
values_list = list(queryset.values())
You cannot send queryset directory as json, because json is just a string. You could use django serializer to apply to your queryset:
from django.core import serializers
serialized_qs = serializers.serialize('json', queryset)
data = {"queryset" : serialized_qs}
return JsonResponse(data)
Also in your javascript you have to do data['queryset'] to access your queryset as json.
I am new to Django, and am stuck attempting to get a variable sent from ajax to be used in the Django view. My view:
def index(request):
if (request.is_ajax()):
username = request.GET['user']
else:
username = ''
context = {'user':username}
return render(request, 'index.html', context)
and the ajax:
$.ajax({
url: '/index/',
type: 'GET',
data: {user: response.name, page: page}
});
My issue is that username does not update in the view, based on the ajax call. I know the ajax call is working properly, because upon looking at the network response it is passing the proper updated username.
What I believe is happening is that the view is loaded, then the ajax call occurs and updates username, but the view is not re-rendered and thus won't change. I have tried putting another render after getting the username, but that did not change anything, and I have also made a separate view for handling the ajax call, but that doesn't seem to work either, since the view always loads without ajax request being true.
What is the way to get this working? Thanks for any help.
If you intend to return a response via Ajax that JavaScript can then use to update your DOM, you need to return an HttpResponse, preferably in JSON format, which can be passed to a handler in your $.ajax call. Example:
import json
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
if request.is_ajax():
username = request.GET.get('user', '')
user = User.objects.get(username=username)
# do whatever processing you need
# user.some_property = whatever
# send back whatever properties you have updated
json_response = {'user': {'some_property': user.some_property}}
return HttpResponse(json.dumps(json_response),
content_type='application/json')
return render(request, 'index.html', {'user': ''})
Then in your JavaScript, you can do:
$.get('/index/', {user: response.name, page: page}, function(json_response) {
console.log(json_response.user.some_property);
});
With this approach, a normal GET request to your view returns a rendered HTML template. For an Ajax request, the view returns an HttpResponse in JSON format that gets passed to the callback in the jQuery $.get call.
To send data to django view via Ajax call, you need to add data to Form and then send in ajax request.
Example:
My view.py :
def index(request):
"""
View function to handle Ajax request for image Link.
:param request: Ajax request data.
:return: image URL.
"""
if request.is_ajax():
try:
username = request.POST['username']
# perform operations on the user name.
except:
e = sys.exc_info()
return HttpResponse(e)
return HttpResponse(sucess)
else:
raise Http404
My template index.html
<html>
<head>
<title>Index</title>
<script>
$(document).ready(function() {
$('#btnSubmit').click(function() {
var data = new FormData();
var username = $('#id_username').val()
data.append('username', username);
$.ajax({
type: 'POST',
url: 'getuser/',
data: data,
processData: false,
contentType: false,
success: function(json) {
alert(json);
}
})
});
});
</script>
</head>
<body>
<h1>Index</h1>
User name: <input type="text" name="fname" id="id_username">
<input type="submit" id ="btnSubmit" name="submit" value="Send Test Push">
</body>
</html>
After this you need to add ajax call url into urls.py.
I have the following ajax call to update a particular field of a model
$("#updateLink").click(function(){
var dec_text = $('#desc_text').val();
$.ajax({
type: "POST",
url:"/users/update_desc/",
data: {
'val': dec_text,
},
success: function(){
$(".display, .edit").toggle();
$("#descText").html(dec_text);
},
error: function(){
alert("Error");
},
});
return false;
});
and my view is this
#csrf_exempt
def update_desc(request):
if request.is_ajax():
if request.method == 'POST':
desc_text = request.POST.get('val', False)
if desc_text:
profile = user.profile
profile.desc = desc_text
profile.save()
return_message = "Sent mail"
return HttpResponse(return_message,mimetype='application/javascript')
I am constantly getting an error message and I don't know how to solve this. I even used the csrf_exempt decorator to workaround if the problem was caused by a missing csrf token but still the problem persists.
Except one ajax post which in my base template all the ajax calls are failing. Can anybody please help to understand what is happening here. I can give some more details if required.
Edit:
I have added the a js file containing this https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax in my base template, so it means it is present in all my templates. And I am using django 1.3 version.
Firstly, you are using POST and not sending a csrf token. Try explicitly sending the csrf token rather than using the decorator csrf_exempt.
One way of doing this is with what I have done in data. That is to fetch the csrf token (or from your own method) and pass it in your arguments.
$.ajax({
url : url,
type: "POST",
data : {csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value},
dataType : "json",
success: function( data ){
// do something
}
});