Version 3 (modified by 18 years ago) ( diff ) | ,
---|
Ajax form submition using Dojo for the client side JavaScript library, and SimpleJson for the client/server communication.
This will take you through all the steps required to get started and to develop a handy form submittion without reload.
What do you need :
- Django
- Dojo (v0.3) http://dojotoolkit.org/ an open source javascript toolkit.
- Simple_Json (v1.3) http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.3/docs/index.html used for java <-> python communication.
What do we want to achieve
I will use the model of my current website, a recipe one. When a registred user see the details of a recipe, he can mark it or update his mark by selecting a small drop down list. That's nice but when he clicks ok the whole page is reloaded :/ let's use some Ajax to make it transparent and for the fancy effect we can add fading status message like "Your mark has been updated". The select box proposes a mark from 1 to 5, it is actually a form which is sent to the server via POST, which in django link to a method in the view.py : def details(request) which do the innerwork for the details page generation.
Installing Json
get the SimpleJson from svn.
svn co http://svn.red-bean.com/bob/simplejson/trunk/ json cd json sudo python setup.py install
Django part
view.py
def details(request): [more stuff] if request.POST: # Get all the mark for this recipe # its not the best way i sould hava an oter entry or table, with total and nbr of marks for # each recipe. list_mark = Mark.objects.values('mark').filter(recipe__pk=r.id) # loop to get the total total = 0 for element in list_mark: total+= element['mark'] # round it total = round((float(total) / len(list_mark)),1) # update the total r.total_mark= total # save the user mark r.save() # Now the intersting part for this tut import simple_json # it was a french string, if we dont't use unicode # the result at the output of json in Dojo is wrong. message = unicode( message, "utf-8" ) # jsonList = simple_json.dumps((my_mark, total, form_message ,message)) return HttpResponse(jsonList) [more stuff, if not POST return render_to_response('recettes/details.html' ...]
url.py
Just normal url.py, remember the path which will point to the wanted method.
from django.conf.urls.defaults import * urlpatterns = patterns('', [...more...] (r'^recettes/(?P<r_cat>[-\w]+)/(?P<r_slug>[-\w]+)/$', 'cefinban.recettes.views.details'), [...more...]
Html template with Dojo javascript
Dojo use
{% load i18n %} {% extends "base.html" %} {% block script %} <script type="text/javascript" src="/media/js/dojo/dojo.js"></script> <script type="text/javascript"> dojo.require("dojo.widget.Tooltip"); dojo.require("dojo.fx.html"); dojo.require("dojo.event.*"); dojo.require("dojo.json"); // point to the same url details.html function sendForm() { dojo.io.bind({ url: '.', handler: sendFormCallback, formNode: dojo.byId('myForm') }); } function sendFormCallback(type, data, evt) { if (type == 'error') alert('Error when retrieving data from the server!'); else // de code the simpleJson answer from django ''details'' method. // it populates a Js array ! straigth so cool ! arrayData = dojo.json.evalJson(data); // now we update the html using the css id as a pointer to the part // we want to update dojo.byId("mark_total").innerHTML = arrayData[1]; dojo.byId("mark_message").innerHTML = arrayData[2]; dojo.byId("mark_status").innerHTML = arrayData[3]; // and the fancy fading effect dojo.lfx.html.highlight("mark_status", [255, 151, 58], 700).play(300); } function init() { var sendFormButton = dojo.byId('sendFormButton'); dojo.event.connect(sendFormButton, 'onclick', 'sendForm') } dojo.addOnLoad(init); </script>
the following HTML code just comes after the upper code snipset.
[... total mark get updated, lets put css id="mark_total" ...] {% if r.total_mark %}<li><b>Score</b>: <span id="mark_total">{{ r.total_mark }}</span>/5</li>{% endif %} [....] {% if not user.is_anonymous %} {% ifnotequal user.id r.owner_id %} <form enctype="multipart/form-data" id="myForm" method="post"> <span id="mark_message">{{mark_message}}</span> <select name="select_mark"> <option value ="1" {% ifequal my_mark 1 %} selected {% endifequal %}>1</option> <option value ="2" {% ifequal my_mark 2 %} selected {% endifequal %}>2</option> <option value ="3" {% ifequal my_mark 3 %} selected {% endifequal %}>3</option> <option value ="4" {% ifequal my_mark 4 %} selected {% endifequal %}>4</option> <option value ="5" {% ifequal my_mark 5 %} selected {% endifequal %}>5</option> </select> </form> <button id="helloButton">Notez</button> <br/> <span id="mark_status">{{ mark_status }}</span> {% endifnotequal %} {% endif %}
And, voila.
To have a demo use guest as login, guest as password here http://ozserver.no-ip.com:345 or if not working here http://www.cefinban.net. Go to index and pick a recipe, update the mark.
You can also have a look at the screenshot here : http://ozserver.no-ip.com/~greg/images/ajaxdjango.png Hope it was useful.
I am using dreamhost for hosting, and no sinplejson is installed. I will ask them to do so, if any one knows a way of installing and using it without being root ? contact me. coulix@…
Gregory Tappero.
Attachments (1)
- json.jar (33.8 KB ) - added by 18 years ago.
Download all attachments as: .zip