Forked from goldhand/Django + Ajax dynamic forms .py
Created
September 30, 2015 09:37
-
-
Save reuf/e36a285389fcbadfadb2 to your computer and use it in GitHub Desktop.
#Django form with Ajax A simple Task model that can be updated using a CBV with an AJAX mixin. The view sends post data with ajax then updates the view with a callback to a DetailView with a json mixin. There is an abstract CBV, AjaxableResponseMixin, based on the example form django docs, that is subclassed in the TaskUpdateView CBV. TaskUpdate…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#models.py | |
class Task(models.Model): | |
title = models.CharField(max_length=255) | |
description = models.TextField() | |
def __unicode__(self): | |
return self.title | |
#views.py | |
import json | |
from django.shortcuts import render_to_response | |
from django.http import HttpResponseRedirect | |
from django.views import generic | |
from django.core.urlresolvers import reverse_lazy | |
from django.http import HttpResponse | |
from braces.views import JSONResponseMixin | |
#http://django-braces.readthedocs.org/ | |
from .models import Task | |
from .forms import TaskForm | |
#https://docs.djangoproject.com/en/1.5/topics/class-based-views/generic-editing/#ajax-example | |
#https://docs.djangoproject.com/en/1.5/topics/class-based-views/mixins/#more-than-just-html | |
class TaskForm(forms.ModelForm): | |
class Meta: | |
model = Task | |
class AjaxableResponseMixin(object): | |
""" | |
Based on the django docs example | |
""" | |
def render_to_json_response(self, context, **response_kwargs): | |
data = json.dumps(context) | |
response_kwargs['content_type'] = 'application/json' | |
return HttpResponse(data, **response_kwargs) | |
def form_invalid(self, form): | |
response = super(AjaxableRetosponseMixin, self).form_invalid(form) | |
if self.request.is_ajax(): | |
return self.render_to_json_response(form.errors, status=400) | |
else: | |
return response | |
def form_valid(self, form): | |
response = super(AjaxableResponseMixin, self).form_valid(form) | |
if self.request.is_ajax(): | |
data = { | |
'pk': self.object.pk, | |
} | |
return self.render_to_json_response(data) | |
else: | |
return response | |
class TaskAJAXView(JSONResponseMixin, generic.DetailView): | |
model = Task | |
content_type = 'application/javascript' | |
json_dumps_kwargs = {'indent': 2} | |
def get(self, request, *args, **kwargs): | |
self.object = self.get_object() | |
context_dict = { | |
'title': self.object.title, | |
'description': self.object.description, | |
} | |
return self.render_json_response(context_dict) | |
class TaskUpdateView(AjaxableResponseMixin, generic.UpdateView): | |
model = Task | |
form_class = TaskForm | |
#urls.py | |
urlpatterns = patterns('', | |
url(r'^tasks/update/(?P<pk>\d+)/$', TaskUpdateView.as_view(), name='task-update'), | |
url(r'^tasks/ajax/(?P<pk>\d+)/$', TaskAJAXView.as_view(), name='task-ajax-detail') | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// javascript | |
// Resources used in this example: | |
// http://net.tutsplus.com/tutorials/javascript-ajax/submit-a-form-without-page-refresh-using-jquery/ | |
// I put this on the template page so it can be manipulated with context | |
function getCookie(name) { | |
// get the csrf token | |
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'); | |
$(":input").change(function() { | |
// validate and process form | |
var title = $("input#id_title").val(); | |
if (title == "") { | |
$("#div_id_title").addClass('error'); | |
$("input#id_title").after('<span class="help-inline">Title required</span>'); | |
$("input#id_title").focus(); | |
return false; | |
} else { | |
$('.help-inline').remove(); | |
$("#div_id_title").removeClass('error'); | |
} | |
var description = $("textarea#id_description").val(); | |
if (description == "") { | |
$("div_id_description").addClass('error'); | |
$("textarea#id_description").after('<span class="help-inline">Required</span>'); | |
$("textarea#id_description").focus(); | |
return false; | |
} else { | |
$('.help-inline').remove(); | |
$("div_id_description").removeClass('error'); | |
} | |
var dataString = | |
'title='+ title | |
+ '&description=' + description | |
+ '&csrfmiddlewaretoken=' + getCookie('csrftoken'); | |
$.ajax({ | |
// django mixin | |
type: "POST", | |
url: "{% url 'task-update' task.id %}", | |
data: dataString, | |
success: function() { | |
$('#message).html("<ul id='message'></ul>") | |
.hide() | |
.fadeIn(1500); | |
$.getJSON("{% url 'task-ajax-detail' task.id %}",function(result){ | |
$.each(result, function(i, field){ | |
$("#result").append("<li>" + i + " : " + field + "</li>"); | |
}); | |
}); | |
} | |
}); | |
return false; | |
}); | |
}); | |
runOnLoad(function(){ | |
$("input#id_title").select().focus(); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!--task_form.html--> | |
{% load staticfiles %} | |
<!--some of these--> | |
{% block jquery %}<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>{% endblock jquery %} | |
<script src="{% static 'js/bootstrap-dropdown.js' %}"></script> | |
<script src="{% static 'js/bootstrap-tab.js' %}"></script> | |
<script src="{% static 'js/bootstrap-transition.js' %}"></script> | |
<script src="{% static 'js/bootstrap-alert.js' %}"></script> | |
<script src="{% static 'js/dynamicForms.js' %}"></script> | |
<ul id=’message’></ul> | |
<div id="task_form"> | |
{% form %} | |
</div> | |
<div> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment