Changes between Initial Version and Version 1 of AjaxDjangoDojoForm


Ignore:
Timestamp:
06/05/06 11:37:01 (16 years ago)
Author:
coulix@…
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AjaxDjangoDojoForm

    v1 v1  
     1'''Ajax form submition using Dojo for the client side JavaScript library, and SimpleJson for the client/server communication.'''
     2
     3As others i was hearing more and more about Ajax, didn't know what it was nor what it does.
     4When i realised it was using JavaScript, it first surprised me since i thought JS was evil. Anyway, now i changed my mind, and i will take you throught all the steps recquired to get started and to develop a handy form submition without reload.
     5
     6
     7== What do you need : ==
     8
     9 - Django
     10 - Dojo (v0.3) [http://dojotoolkit.org/] an open source javascript toolkit.
     11 - Simple_Json (v1.3) [http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.3/docs/index.html] used for java <-> python communication.
     12
     13
     14== What do we want to achieve ==
     15I will use the model of my current website, a recipe one.
     16When a registred user see the details of a recipe, he can mark it or update his mark by selection a small drop down list.
     17That'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,
     18we can add fading status message like "Your mark has been updated".
     19The 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
     20in the view.py : ''def details(request)'' which do the innerwork for the details page generation.
     21
     22
     23== Installing Json ==
     24get the SimpleJson from svn.
     25
     26{{{
     27svn co http://svn.red-bean.com/bob/simplejson/trunk/ json
     28cd json
     29sudo python setup.py install
     30}}}
     31
     32== Django part ==
     33'''view.py'''
     34{{{
     35def details(request):
     36        [more stuff]
     37        if request.POST:
     38                # Get all the mark for this recipe
     39                # its not the best way i sould hava an oter entry or table, with total and nbr of marks for
     40                # each recipe.
     41                list_mark = Mark.objects.values('mark').filter(recipe__pk=r.id)
     42                # loop to get the total
     43                total = 0
     44                for element in list_mark:
     45                        total+= element['mark']
     46                # round it
     47                total = round((float(total) /  len(list_mark)),1)
     48                # update the total
     49                r.total_mark= total
     50                # save the user mark
     51                r.save()
     52
     53                # Now the intersting part for this tut
     54                import simple_json
     55                # it was a french string, if we dont't use unicode
     56                # the result at the output of json in Dojo is wrong.
     57                message = unicode( message, "utf-8" )
     58                #
     59                jsonList = simple_json.dumps((my_mark, total, form_message ,message))
     60                return HttpResponse(jsonList)
     61        [more stuff, if not POST return render_to_response('recettes/details.html' ...]
     62}}}
     63
     64'''url.py'''
     65
     66Just normal url.py, remember the path which will point to the wanted method.
     67{{{
     68from django.conf.urls.defaults import *
     69
     70urlpatterns = patterns('',
     71        [...more...]
     72        (r'^recettes/(?P<r_cat>[-\w]+)/(?P<r_slug>[-\w]+)/$', 'cefinban.recettes.views.details'),
     73        [...more...]
     74}}}
     75
     76
     77== Html template with Dojo javascript ==
     78'''Dojo use'''
     79
     80{{{
     81{% load i18n %}
     82{% extends "base.html" %}
     83{% block script %}
     84 <script type="text/javascript" src="/media/js/dojo/dojo.js"></script>
     85 <script type="text/javascript">
     86 
     87    dojo.require("dojo.widget.Tooltip");
     88    dojo.require("dojo.fx.html");
     89    dojo.require("dojo.event.*");
     90    dojo.require("dojo.json");
     91
     92    // point to the same url details.html       
     93    function sendForm()
     94    {
     95     dojo.io.bind({
     96                    url: '.',
     97                    handler: sendFormCallback,
     98                    formNode: dojo.byId('myForm')
     99                });
     100    }
     101
     102  function sendFormCallback(type, data, evt)
     103    {
     104    if (type == 'error')
     105        alert('Error when retrieving data from the server!');
     106    else
     107        // de code the simpleJson answer from django ''details'' method.
     108        // it populates a Js array ! straigth so cool !
     109        arrayData = dojo.json.evalJson(data);
     110        // now we update the html using the css id as a pointer to the part
     111        // we want to update
     112        dojo.byId("mark_total").innerHTML = arrayData[1];
     113        dojo.byId("mark_message").innerHTML = arrayData[2];
     114        dojo.byId("mark_status").innerHTML = arrayData[3];
     115        // and the fancy fading effect
     116        dojo.lfx.html.highlight("mark_status", [255, 151, 58], 700).play(300);
     117    }
     118   
     119    function init()
     120    {
     121        var sendFormButton = dojo.byId('sendFormButton');
     122        dojo.event.connect(sendFormButton, 'onclick', 'sendForm')
     123    }
     124 
     125    dojo.addOnLoad(init);
     126       
     127</script>
     128}}}
     129
     130the following ''HTML code'' just comes after the upper code snipset.
     131
     132{{{
     133[... total mark get updated, lets put css id="mark_total" ...]
     134{% if r.total_mark  %}<li><b>Score</b>: <span id="mark_total">{{ r.total_mark }}</span>/5</li>{% endif %}
     135[....]
     136{% if not user.is_anonymous %}
     137    {% ifnotequal user.id r.owner_id %}
     138        <form enctype="multipart/form-data" id="myForm" method="post">
     139            <span id="mark_message">{{mark_message}}</span>
     140               <select name="select_mark">
     141                    <option value ="1" {% ifequal my_mark 1 %} selected {% endifequal %}>1</option>
     142                    <option value ="2" {% ifequal my_mark 2 %} selected {% endifequal %}>2</option>
     143                    <option value ="3" {% ifequal my_mark 3 %} selected {% endifequal %}>3</option>
     144                    <option value ="4" {% ifequal my_mark 4 %} selected {% endifequal %}>4</option>
     145                    <option value ="5" {% ifequal my_mark 5 %} selected {% endifequal %}>5</option>
     146               </select>
     147       </form>
     148      <button id="helloButton">Notez</button>
     149      <br/>
     150      <span id="mark_status">{{ mark_status }}</span>
     151     {% endifnotequal %}
     152{% endif %}
     153}}}
     154
     155And, voila.
     156
     157To 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].
     158Go to index and pick a recipe, update the mark.
     159
     160You can also have a look at the screenshot here :  [http://ozserver.no-ip.com/~greg/images/ajaxdjango.png]
     161Hope it was useful.
     162
     163I 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
     164root ? contact me. coulix@gmail.com
     165
     166Gregory Tappero.
     167
     168
     169
Back to Top