Using Ajax call to update a Django view - ajax

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.

Related

Converting formData to forms.Form in django

I would like to allow user to key in a quiz code and gets an alert to tell whether if the code is still invalid without refreshing the page. I already read a lot of Django AJAX and JQuery tutorials but most of them seem outdated because they do not cover the part where csrf token must be send.
In my settings.py, I set CSRF_USE_SESSIONS to True.
This is my forms.py
class codeForm(forms.Form):
code = forms.IntegerField(label='Question Code')
In my html file, I have this
<form class="card__form" id="code-form" method="POST">
{% csrf_token %} <script type="text/javascript"> // using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val(); </script> {{form.as_p}
<center><input type="submit" class="btn btn-primary card__submit" id="submit_code"></center>
Just before the tag, I have this :
<script>
$(document).ready(function(){
$("#submit_code").click(function(){
alert("Text: ");
event.preventDefault();
var myform = document.getElementById("code-form");
var form = new FormData(this);
form.append('csrfmiddlewaretoken', csrftoken);
$.ajax({
data : form,
dataType:'json',
type: 'POST',
method: 'POST',
url: '{% url 'student:process_code' %}',
contentType: false,
processData: false,
success: function(context) {
alert(context.msg);
},
error: function(context) {
alert(context.msg);
}
});
});
});
</script>
In my views.py
def process_code(request):
context = {}
if request.method == 'POST':
form = codeForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
code = cd.get('code')
print('yay')
if code.isdigit():
The unexpected result was the form is not valid (form.is_valid() = false). Thus, I think my formData object is not converted to a valid forms.Form type.
I also tried to use form = codeForm(request.POST['code']) but it return more error.
How can I get around this? I prefer not to use serialize() because I read that it cannot be used for uploading files which will be my next feature to work on after this has settled. I wanted to use forms.Form because it has cleaned_data method. If you could provide a good solution although not using forms.Form but with good reasoning, I will appreciate it. Thank you so much
try FormData(myform), not "this"

Django form submitted with ajax redirects to form action instead of calling success

I have simple form
class TimeForm(forms.Form):
time = forms.TimeField()
date = forms.DateField()
def clean_date(self):
time = self.cleaned_data['time']
date = self.cleaned_data['date']
date_time = datetime.combine(date, time)
if datetime.now() > date_time:
raise ValidationError("datetime error")
return start_date
with class based view
class TimeView(View):
#staticmethod
def post(request):
form = TimeForm(request.POST)
if form.is_valid():
# do something
json_data = json.dumps({'some_record': value})
else:
json_data = json.dumps({'errors': form.errors})
return HttpResponse(json_data, content_type='application/json')
In html I have standard form with submit connected do ajax
<form action="/time_url/" method="POST" id="time_form">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
<script>
$('#time_form').submit(function(event) {
event.preventDefault();
$.ajax({
type: "POST",
url: '/time_url/',
dataType: 'json',
data: $(this).serialize(),
success: function(data, textStatus, jqXHR){
alert('yay');
}
})
});
</script>
and I'd like to be able to submit this form without page reload. Everything seems to work perfectly but success function of ajax is not triggered, instead page is redirected to /time_url/ with json data. It doesn't matter wheter form is valid nor not, it's always redirected.
I've tried also with
return JsonResponse(form.errors.get_json_data())
instead of
return HttpResponse(json_data, ...)
as suggested here Django form submit with ajax but without success.
I'm new to javascript but for me it looks like problem with ajax, since proper data is served by server.
Thanks for any tips.

AJAX gets access to Django HttpResponse variables

I am writing a small test app for a bigger project. I would like to use asynchronously FileReader() to read a txt file from client side and pass the textbody to the Django server by using AJAX. When the server succeeds to get the "posted" text, it will return the length of the text. It worked well on the server and I got what I expected. But now I would like to pass the size of the text(length) back to the client and display it somewhere on the web page asynchronously. But failed... Here is my code:
HTML
<script type="text/javascript">
var render_text = function(csvFile, onLoadCallback){
var reader = new FileReader();
reader.onload = onLoadCallback;
reader.readAsText(csvFile);
}
$(document).ready(function(){
$("#id_csvFileInput").on("change", function(e){
render_text(this.files[0], function(e){
var text = e.target.result;
$.ajax({
url: "",
type: 'POST',
async: true,
data: {'text': text},
success: function(data){
$("#id_test").text(data.size);
}
});
});
});
});
</script>
<p>
<input type="file" name="csvFileInput" id="id_csvFileInput" accept=".csv">
</p>
<div>
<p>Waiting for reponse context....</p>
<span id="id_test">?</span>
</div>
View.py
# Home page.
#csrf_exempt
def home(request):
template = 'hbvapp/home.html'
context = {}
if request.method == "POST" and request.is_ajax():
context['test'] = request.POST.get('text')
context['size'] = len(context['test'])
print context['size']
return render(request, template, context)
else:
return render(request, template)
ANY HELP WILL BE DEEPLY APPRECIATED !
Reagards
try it
from django.http import JsonResponse
if request.method == "POST" and request.is_ajax():
context['test'] = request.POST.get('text')
context['size'] = len(context['test'])
print context['size']
return JsonResponse(context)
# ^^^^^
more details jsonresponse
you can send it this way also:
context['test'] = request.POST.get('text')
context['size'] = len(context['test'])
print context['size']
return HttpResponse(json.dumps(context), content_type='application/json')
and in you js you can access it like this:
success: function(data){
$("#id_test").text(data['size']);
}

Json does not work in Django with Ajax

I want to make an ajax request in a Django framework. However, I don't pass to get data from the client in json. It works when I don't use Json.
If I use dataType:'json' with a {'a': 'value'} in the ajax, I can't get it in the view.py, the result is nothing...
However if I use data:$(this).serializeArray() in the ajax I can get result with request.POST. However, I really need to customize my data and send to my view.py other data than the data from the form. I would like to send a {'a', 'mydata', 'form': myformdata}...
Is there a way to do it?
template:
<form id="ajax2" action="/seghca/test-post/" method="post">{% csrf_token %}
Nom : <input type="text" name="nom" value="" id="nom"/><br/>
prenom : <input type="text" name="prenom" value=""/><br/>
<input type="submit" value="Envoyer"/>
</form>
<div id="result"></div>
javascript:
$(document).ready(function(){
// POST AJAX
$("#ajax2").submit( function() {
var urlSubmit = $(this).attr('action');
var data = $(this).serializeArray();
data.push({
key: "keyName",
value: "the value"
});
$.ajax({
type: "POST",
url: urlSubmit,
dataType: "json",
data : data,//$(this).serializeArray(),
success: function(response){
var json_response = JSON.parse(response);
// now get the variables from the json_response
$('#result').html(json_response.html);
}
});
return false;
});
});
view.py (the ajax launch the test_post view, home2 is the view of the formular):
from datetime import datetime
from django.http import HttpResponse, Http404
from django.shortcuts import redirect, render
from seghca.models import Article
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.template import RequestContext
from django.views.decorators.csrf import csrf_exempt
import json
def home2(request):
return render_to_response('seghca/form.html', context_instance=RequestContext(request))
#csrf_exempt
def test_post(request):
data = {'html': request.POST['key']}
return HttpResponse(json.dumps(data), mimetype="application/json")
When you are using ajax view you should return the data back from your view in the json form:
data = {'html': request.POST['input']}
return HttpResponse(json.dumps(data), mimetype="application/json")
Second it is necessary to parse the response first on client side:
success: function(response){
var json_response = JSON.parse(response);
// now get the variables from the json_response
$('#result').html(json_response.html);
}
Third if you need to pass the form data along with some more info you can do:
var data = $(this).serializeArray();
data.push({
key: "keyName",
value: "the value"
});
Fourth you are missing csrf token.
change data: data, to data: {'data': JSON.stringify(data)},
and you'll be able to access the serialized version of your data via POST['data'] in django. Keep in mind that if you want to use this in django you have to deserialize it, for instance json.loads(POST['data'])
I have your same needs. My solution was:
The AJAX request:
var posturl = $('#'+formid).prop('action');
$.ajax({
async:false,
type: "POST",
dataType: "json",
contentType: "application/x-www-form-urlencoded",
url : posturl,
data : $('#'+formid).serialize() + '&mode=ajax', //&mode=ajax is my custom data
success:function(response){
console.log(response);
alert(response.message);
},
timeout:10000
});
In the views.py:
data = {'error': '0', 'message': 'all was ok'}
return HttpResponse(json.dumps(data), mimetype="application/json")
The above should work for you. My test was with Django 1.6 and Python 2.7.5

Ajax + Django: how to properly send few things from client browser to server?

In my app, there are several categories of data that need to be sent from client browser to server.
the back end is in Django. I am trying to using Ajax to POST data to the view function in Django, and then return something to client. The codes I've tried are as follows:
In Django urls.py:
(r'^testPost/', testPost),
Django View function:
def testPost(request):
print request
if request.method == 'GET':
rID = request.GET['rID']
rName = request.GET['rName']
elif request.method == 'POST':
rID = request.POST['rID']
rName = request.POST['rName']
return HttpResponse("ID: " + str(rID) + " and Name: " + str(rName))
Front-end AJAX call (ExtJS 3.3):
Ext.Ajax.request({
url: 'XXXX/testPost/?',
method: 'POST',
jsonData: Ext.encode({
"rID": 1333,
"rName": 'test'
}),
headers: {
'Content-Type': 'application/json'
},
success: function (response, opts){
console.log(response.responseText);
},
failure:function (response, opts){
console.log(response.responseText);
}
});
It seems something is wrong with URL setting. got an error response:
Some unexpected error occurred. Error text was: HTTP Error 403: FORBIDDEN
UPDATE:
1. based on ldiqual's advice, put
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
in the view script
changed ExtJS ajax request code from using jsonData to params:
params: {
"rID": 1333,
"rName": 'test'
}
issue is solved for my case.
For ajax POSTing, you'll need CSRF token, and it's unwise to simply disable it with #csrf_exempt since it defeats the purpose. If you don't want CSRF protection, then remove 'django.middleware.csrf.CsrfViewMiddleware' from MIDDLEWARE_CLASSES.
The Django docs provide a jQuery function that will automatically add the token to all ajax requests: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
I don't have any experience with ExtJS, but you'll want to find an equivalent. Here are some snippets you could look at:
https://stackoverflow.com/a/5485616/338903
http://djbook.ru/examples/22/
http://www.sencha.com/forum/showthread.php?134125-Django-1.3-Login-with-ExtJS-4-and-CSRF
In your template file (assume that you use jQuery library):
<form id="MyForm" action="." method="POST">
{% csrf_token %}
{{ form.as_table }}
<input type="submit" class="default" value="Save" onclick="PostThisToAjax(jQuery("#MyForm").serialize()); return false;" />
</form>

Resources