Code


Version 2 (modified by anonymous, 8 years ago) (diff)

First Introduction

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 :

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 selection a small drop down list. That's nice but when he cliks 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)

Download all attachments as: .zip