El Blog de Trespams

Blog personal sobre tecnologia, gestió de projectes i coses que se me passen pel cap

Dajaxproject, primera part

Una de les preguntes més recurrents en les llistes de Django, junt amb la de quin editor fer servir és la de com fer cridades AJAX i quina llibreria utilitzar.

Django és agnòstic en el que fa a les llibreries javascript, tot i això la part de l'admin fa servir jQuery, però oficialment no hi ha cap llibreria especialment recomanada, Django és pot utilitzar amb qualsevol llibreria i dependrà del projecte que en triem una o altra.

El problema de que no es faci cap recomanació de com integrar cridades AJAX amb Django ens dóna molta llibertat, però també te l'emperò de que no hi ha cap guia de bones pràctiques sobre com fer-ho, des d'on posar la llibreria, quin nom li hem de donar, si la posam al views.py o no.

El la comunitat de codi obert quan hi ha un buid així i una necessitat ben aviat sorgeixen projectes que intenten donar una resposta. Un d'aquests projectes és el que us present en aquest article el dajaxproject.

Djaxaproject són de fet dues llibreries, dajaxice i dajax, la primera podríem dir que respon a la necessitat que us comentava de fer més senzilla la comunicació asíncrona entre les aplicacions Django y el codi javascript, la segona, dajax està molt més orientada cap a la capa de presentació i sobretot està lligada a un bastiment de javascript en concret, encara que tenim certa llibertat a l'hora de triar-lo.

En aquest apunt veurem primer Dajaxice i en un següent apunt faré també cinc cèntims de dajax.

Instal·lació

Suposaré com tantes vegades que teniu un virtualenv creat i Django instal·lat. També hem de partir d'un projecte base.

El primer que hem de fer és instal·lar la llibreria, per això bastarà fer un

pip install django-dajaxice

La documentació explica força bé el procés, així que resumeixo:

  1. Posar dajaxice dins la secció INSTALLED_APPS de settings.py
  2. Assegurar-nos que tenim eggs.Loader descomentat als TEMPLATE_LOADERS
  3. Assegurar-nos que django.core.context_processors.request és dins el TEMPLATE_CONTEXT_PROCESSORS, si no ho heu fet ja, el meu consell és que copieu tot el TEMPLATE_CONTEXT_PROCESSORS que hi ha a la documentació, ja que a poc que l'aplicació cresqui segur que necessitareu afegir-ne algun.
  4. Afegim als settings.py el prefixe que farem servir per distingir les urls de dajaxice de les de urls normals de la nostra aplicació, per exemple la documentació ens diu posar DAJAXICE_MEDIA_PREFIX="dajaxice".

Amb això ja hem fet par de la fontaneria, ara ve la part més interessant i la màgia d'aquesta aplicació.

Organitzant l'AJAX

Dajaxice el farà és utilitzar el prefixe que hem configurat per tractar certes urls com a cridades AJAX. Djaxice el que ens permet és registrar automàticament les funcions que es publicaran com a cridades AJAX utilitzant un mecanisme semblant al que fa dervir Django per a l'admin.

D'aquesta manera, una vegada modificat l'arxiu urls.py podem anar creant les funcions a publicar dins un arxiu ajax.py i registrar les funcions. Així l'arxiu urls.py ens ha de quedar com:

# !/usr/bin/python
from django.conf.urls.defaults import patterns, include, url
from dajaxice.core import dajaxice_autodiscover
from django.contrib import admin
from django.conf import settings

admin.autodiscover()
dajaxice_autodiscover()
urlpatterns = patterns('', url(r'^admin/', include(admin.site.urls)),
(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, include('dajaxice.urls')), )

Utilitzant AJAX a les nostres plantilles

Dajaxice es capaç de posar dins la nostra plantilla el codi que necessitam per fer les cridades AJAX i publicar les funcions que farem servir a partir del codi Python (ja ho veurem un poc més endavant). Per fer-ho fa servir una llibreria que s'ha de carregar.

Així a la part de càrrega de llibreries de la nostra plantilla haurem d'afegir: dajaxice_templatetags. Si encara no heu carregat cap llibreria doncs quedaria com {% load dajaxice_templatetags %}.

Una vegada carregada la llibreria posarem el tag que genera el codi javascript {% dajaxice_js_import %}. Ho podeu posar a la capçalera o al peu de la plana. Personalment, com que ho sol fer servir junt amb jQuery, ho pos al peu, abans de l'utilització de les llibreries, per tal de millorar la velocitat de càrrega de les planes.

Aquest codi es gener dinàmicament mentre estam desenvolupant. Us avís que de tant en tant es queda carregat en memòria i certs canvis requereixen reiniciar el servidor de desenvolupament. Si veis que heu publicat una funció i no surt, reiniciau el servidor.

En producció la llibreria té una opció per generar directament l'arxiu javascript i poder tractar-lo com un fitxer estàtic més.

L'estructura d'una plantilla bàsica amb djaxice seria doncs

{% load dajaxice_templatetags %}
<html>
<head>
<title>My base template</title>
<!-- també al peu depen de l'aplicació -->
{% dajaxice_js_import %}
</head> ....
</html>

Creant la nostra primera cridada AJAX

Com us comentava més amunt, una de la gràcia de dajaxice és que ens permet organitzar les nostres cridades AJAX. Així el que farem serà crear un arxiu ajax.py dins la nostra aplicació, de manera que podem agrupar cridades per aplicació.

Suposem que hem creat una aplicació anomenada main, la posam al settings.py del projecte i cream l'arxiu ajax.py

Crear una funció i publicar-la per a que la servim via AJAX és tan senzill com això:

# !/usr/bin/python # -*- coding: utf-8 -*-
from django.utils import simplejson
from dajaxice.decorators import dajaxice_register


@dajaxice_register
def hello_world(request):
return simplejson.dumps({'message': 'Hello World'})

És a dir, importam simplejson per a fer la transformació cap a json, que és el que volem servir (o xml, o html, tant fa), cream una funció com ho feim al views.py de Django i la decoram amb
dajaxice_register. Això junt el autodiscover que hem posat a urls.py fa que ara la nostra aplicació pugui respondre a cridades AJAX.

Cridant des de l'html

Per cridar a la nostra funció es pot fer directament amb l'event onclick directament a l'HTML,però a mi particularment em fa molta grima tenir aquesta mescladissa, així que prefereixo tirar de jQuery encara que per fer la crida AJAX no el faci servir. Recordem que l'important no és el mètode amb que es fa la crida, sinó l'organització i facilitat de mantenimient (i depuració) que ens dóna la llibreria.

Així, en el meu cas quedaria:

<script src="https://ajax.googleapis.com/ ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<script type="text/javascript"> $(function(){ $('#testme').click(function(event){ event.preventDefault(); Dajaxice.main.hello_world(test_callback); }); function test_callback(data){ if (data==Dajaxice.EXCEPTION){ alert('Opps, alguna cosa dolenta ha passat'); } else { alert(data); } } }); </script>

on #testme fa referència a un enllaç al qual hem assignat l'event.

L'interesant d'això és que tenim a la nostra disposició una funció javascript que mapeja la que tenim al codi Python i a la qual podem cridar amb uns paràmetres. El primer d'ells és la funció de tornada (el callback) que utilitzarem per gestionar la resposta i l'altra és un paràmtre codificat com json que passarà com a paràmetre cap a la funció.

Hem de dir que dajaxice sempre fa un POST contra la url, gestionant els problemes de CSRF.

Si posam DAJAXICE_DEBUG=True al settings.py o millor dit, ve així per defecte, a la consola de desenvolupament de Django podem veure tant la cridada que fem com la resposta i els errors que hi pugui haver.

La funció de tornada es defineix amb un paràmetre que contindrà el valor de retorn de la nostra cridada AJAX. Si és un json podrem accedir als valors directament, però com he comentat abans, no estam limitats a tornar json, podem tornar una cadena de text, xml, html, ... el que necessitem i poguem tractar amb javascript.

És interessant veure com es tracten els errors o les excepcions. Si hi ha problems al nostre codi Python i es llança una excepció, dajaxice la capturarà i llavors data contindrà el valor Dajaxice.EXCEPTION, amb la qual cosa sabem que quelcom ha anat malament.

He de fer servir sempre Dajaxice?

Depèn, algunes vegades serà més convenient fer una cridada directa amb jQuery, per exemple quan volem tenir més control del que passa quan s'inicia la cridada, o volem poder-la cancel·lar.

El cert, però, és que dajaxice ens permet organitzar millor el codi i gestionar d'una manera sistemàtica les nostres cridades AJAX. Com sempre no hi ha cap veritat absoluta, potser servirà en el 80% dels casos i això ja significa una gran ajuda.

blog comments powered by Disqus