AJAXify Django Forms
By Justin

AJAX, short for asynchronous JavaScript and XML, is a technology that enables asynchronous web applications. Basically, it makes your web app run without the need to reload the page every time an action happens.
Think about the Facebook Like button, you click the button and it shows that you've liked the item. The page doesn't reload but the data is saved. That's the key.
Ajax = Save or Get Data without page reload.
So how do you do it?
AJAX is a client-side technology because it requires the client-side to communicate with the server-side. So basically, JavaScript needs to talk to Django.
So we need to setup our Django backend to work with the frontend.
Guide prerequisites:
- Django Installed windows | mac or linux
- Try Django (latest) complete
Reference code on github
Watch the video
Setup Django Backend
1. Django form
# yourapp.forms.py
from django import forms
class JoinForm(forms.Form): # or forms.ModelForm
email = forms.EmailField()
name = forms.CharField(max_length=120)
2. Standard Form View
# yourapp.views.py
from django.views.generic import FormView
from .forms import JoinForm
class JoinFormView(FormView):
form_class = JoinForm
template_name = 'forms/ajax.html'
success_url = '/form-success/'
3. Update URL routing
# yourproject.urls.py
from django.conf.urls import url
from django.contrib import admin
from yourapp.views import JoinFormView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^join/', JoinFormView.as_view()),
]
4. Ajax-fied Form View
# from step 2
from django.http import JsonResponse
class JoinFormView(FormView):
form_class = JoinForm
template_name = 'forms/ajax.html'
success_url = '/form-success/'
def form_invalid(self, form):
response = super(JoinFormView, self).form_invalid(form)
if self.request.is_ajax():
return JsonResponse(form.errors, status=400)
else:
return response
def form_valid(self, form):
response = super(JoinFormView, self).form_valid(form)
if self.request.is_ajax():
print(form.cleaned_data)
data = {
'message': "Successfully submitted form data."
}
return JsonResponse(data)
else:
return response
5. Create AJAX Mixin
# yourapp.mixins.py
class AjaxFormMixin(object):
def form_invalid(self, form):
response = super(AjaxFormMixin, self).form_invalid(form)
if self.request.is_ajax():
return JsonResponse(form.errors, status=400)
else:
return response
def form_valid(self, form):
response = super(AjaxFormMixin, self).form_valid(form)
if self.request.is_ajax():
print(form.cleaned_data)
data = {
'message': "Successfully submitted form data."
}
return JsonResponse(data)
else:
return response
6. Update Ajax-fied Form View
# yourapp.views.py
from .mixins import AjaxFormMixin
class JoinFormView(AjaxFormMixin, FormView):
form_class = JoinForm
template_name = 'forms/ajax.html'
success_url = '/form-success/'
Setup Frontend
1. Base.html on Django
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Base Template</title>
</head>
<body>
<div>
{% block content %}{% endblock content %}
</div>
<!-- jQuery (required for this Ajax tutorial) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</body>
</html>
2. Django Template
{% extends "base.html" %}
{% comment "template_location" %}
'forms/ajax.html'
{% endcomment %}
{% block content %}
<form class='my-ajax-form' method='POST' action='.' data-url='{{ request.build_absolute_uri|safe }}'>
{% csrf_token %}
{{form.as_p|safe}}
<button type='submit'>Submit</button>
</form>
{% endblock content %}
3. The Required jQuery (JavaScript code):
<script>
$(document).ready(function(){
var $myForm = $('.my-ajax-form')
$myForm.submit(function(event){
event.preventDefault()
var $formData = $(this).serialize()
var $thisURL = $myForm.attr('data-url') || window.location.href // or set your own url
$.ajax({
method: "POST",
url: $thisURL,
data: $formData,
success: handleFormSuccess,
error: handleFormError,
})
})
function handleFormSuccess(data, textStatus, jqXHR){
console.log(data)
console.log(textStatus)
console.log(jqXHR)
$myForm.reset(); // reset form data
}
function handleFormError(jqXHR, textStatus, errorThrown){
console.log(jqXHR)
console.log(textStatus)
console.log(errorThrown)
}
})
</script>
4. Enable Django CSRF-ready AJAX Calls
This is directly from the Django docs. Put this code before any jQuery that uses AJAX as a catch-all for cross site request forgery protection (CSRF).
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});