Json does not work in Django with Ajax - 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

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"

Flask - Validate several forms on Ajax request

I'm trying to validate four forms from an Ajax request. My problem is that only one form is validated (geometry_building_form). The others do not contain errors, only an empty dictionary.
Another problem I have is that the validate_on_submit method does not work, I have to use the validate method.
This is the Flask view.
#app.route('/', methods=['GET', 'POST'])
#app.route('/index', methods=['GET', 'POST'])
def building():
building_parameters_form = BuildingParametersForm()
building_geometry_form = BuildingGeometryForm()
wind_form = WindForm()
topography_form = TopographyForm()
if request.method == 'POST':
if building_geometry_form.validate() and building_parameters_form.validate() and wind_form.validate() and topography_form.validate():
return redirect('/index')
else:
return jsonify(data=wind_form.errors) #Testing the wind form
return render_template('wind/building.html', bp_form=building_parameters_form,
bg_form=building_geometry_form, w_form=wind_form, t_form=topography_form)
This is the Ajax code.
<script>$(document).ready(function() {
$("#button").click(function(event) {
var csrf_token = "{{ csrf_token() }}";
var url = "{{ url_for('building') }}";
event.preventDefault();
$.ajax({
type: "POST",
url: url,
dataType: 'json',
data: $('#geometry-form, #parameters-form, #wind-form, #topography-form').serialize(),
success: function (data) {
console.log(data)
}
});
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrf_token)
}
}
})
});
});
</script>
FormFields are useful for editing child objects or enclosing multiple related forms on a page which are submitted and validated together. While subclassing forms captures most desired behaviours, sometimes for reusability or purpose of combining with FieldList, FormField makes sense. (Taken from Documentation)
With that in mind-- you may want to create a wrapping form that encloses your sub-forms:
from wtforms import FormField
class BuildingForm(Form):
building = FormField(BuildingGeometryForm)
wind = FormField(WindForm)
topography = FormField(TopographyForm)
The later when you're processing the request, form = BuildingForm() will allow you to do form.validate_on_sumbit() and it will validate and enclose the various subforms as expected.

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']);
}

Using Ajax call to update a Django view

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.

Django Ajax-Jquery does not fetch the data

I am not able to get the input text field data with id city_name from the form via jQuery-Ajax method.
The error that I keeps getting is "NetworkError: 403 FORBIDDEN - http://127.0.0.1:8000/dashboard".
I know how to get the data using hidden field type, but that option cannot be used here and moreover, getting data from hidden field is now an outdated method. So, how can I get data using Django-AjaxJquery method.
HTML
<form type = "POST">
{% csrf_token %}
<input type="text" placeholder = "Enter City Name" id = "city_name">
<input type="button" value = "On" id="on">
<input type="button" value = "Off" id="off">
</form>
JS File
$(function(){
$("#on").click(function (event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "dashboard",
data : {
'city_name' : $("#city_name").val(),
},
});
});
});
View.py
#login_required
def dashboard(request):
ctx = {}
if request.is_ajax():
city_name = request.POST['city_name']
print city_name
return render_to_response('dashboard/dashboard.html',ctx, context_instance = RequestContext(request))
urls.py
urlpatterns = patterns('',
url(r'^dashboard$','apps.dashboard.views.dashboard', name = 'llumpps_dashboard'),
)
It is missing the CSRF token in the request.
You can either use #csrf_exempt decorator for your view like:
#login_required
#csrf_exempt
def dashboard(request):
...
Or send the token along with the request:
$.ajax({
type: "POST",
url: "dashboard",
data : {
'csrfmiddlewaretoken': $('input[name="csrfmiddlewaretoken"]').val();
'city_name' : $("#city_name").val(),
},
complete: function () {
// do whatever here
}
});
Read more about CSRF and AJAX in Django here: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
Hope it helps.

Resources