Török Gábor, műszaki informatikus hallgató, többek között a Weblabor egyik szerkesztője, és az online marketing megoldásokat szállító WebMánál fejlesztő.
Az előadás célja, hogy átfogó képet nyújtson egy korszerű ajaxos webalkalmazás felépítéséről, amelynek backendjét Django, frontendjét a GWT szolgáltatja, de valójában bármelyik építőköve lecserélhető egy másik komponensre.
Az Ajaxról előljáróban néhány szó.
Az Ajax észszerű alkalmazása csökkenti a kiszolgáló terhelését, mert kevesebb lesz általa az adatforgalom, csak azok az oldal részek töltődnek újra, amelyeken valóban változás történt, adott esetben kevesebb lekérdezést kell kiszolgálnia a webszervernek, továbbá várhatóan kevesebb lesz a felemésztett sávszélesség költsége is. A helyes ajaxos fejlesztés metodológia megköveteli a programozótól, hogy jobban szétválassza a template-et (megjelenést) az üzleti logikától.
A Django áttekintése.
A Django Python alapú webes keretrendszer, így a Python nyújtotta valamennyi jellemzővel bír. Méltán címkézhetjük fel a robosztus, rapid, hatékony jelzőkkel: robosztus, mert ### gyors vele a fejlesztés; végül hatékony, mert bájtkódként ragyogó teljesítményt érhetünk el vele. A Pythont ellentétben a szintén pythonos vízeken evező Turbogears-zel többnyire nem meglévő komponensekből, hanem from the scratch építették fel.
A Django egyik erőssége az adatmodellekből származtatott, automatikusan felépített admin rendszer, amely megkönnyíti a modellek karbantartását. A Django szigorúan MVC felépítésű keretrendszer, noha a saját terminológiájában inkább MTV-nek, azaz Model-Template-View-nak nevezik a mögötte rejlő koncepciót. A sablon rendszere gyors, nem kötött az XML-hez, így bármi kiszolgálható vele (legyen az XHTML, CSV, JSON vagy akár egy email), és teljesen leválasztja az alkalmazás logikát a megjelenési rétegről. Apache és Lighttpd webszerverrel is üzembe helyezhető. Támogatja a többnyelvűséget (i18n).
A Djangot konkrét (üzleti) probléma megoldására kezdték el fejleszteni, valós igényekek kielégítésére született. Ebből a szempontból hasonlatos a Ruby on Railshez, és talán ez a jellemző fogja hosszú távon sikerét és talpon maradását garantálni, míg vele szemben a Turbogearst „csak” a közösség indította útjára, így kisebb a fejlesztőkön a nyomás, adott esetben kevésbé inspiráltak is emiatt. Sok bírálat éri a Django fejlesztőket, hogy mindent maguk akarnak megírni, nem használnak fel meglévő komponenseket (NIH szindróma). Ez természetesen nincs így, a Django felhasznál kiforrott építőköveket, csupán azokat készítik el a kóderek maguk, amely funkció ellátására még nem érhető el a számukra szükséges tudású csomag. A Django (és például a Rails) legfőbb filozófiai vonása a DRY elv: minimalizáljuk a kód redundanciát, ne kelljen ugyanazt a problémát többször megoldanunk.
A Djangóról további részletek a 2006-os Magyarországi Web Konferencián tartott Django: Python on Rails előadásomban olvashatók.
A Django és az Ajax kapcsolatáról.
A Django nem érkezik saját JavaScript toolkittel, de moduláris, rugalmas felépítése miatt lehetőséget teremt arra, hogy könnyen csatolhassuk a keretrendszerhez a kedvenc függvénytárunkat (JQuery, YUI, MochiKit stb.). Az MTV felépítésből és az URL központúságból fakadóan egyszerűen, on the top of lehetséges ajaxos API-val egy már meglévő alkalmazás bővítése. Flexibilis, nem XML-hez kötött template rendszerét felhasználhatjuk arra, hogy plain text vagy JSON üzenetekkel kommuniikáljunk a frontend felé. A Django már korábban is említett admin felülete pedig mindehhez kényelmes backendként szolgál admin felületével.
django.utils.simplejsondjango.core.serializers
urlpatterns = patterns('',
('^$', webconf.blog.index),
('^/archives/$', webconf.blog.archives),
('^/(\d{4})(\d{2})(\d{2})/(?P<slug>\w+)/$',
webconf.blog.single),
)
from django.shortcuts import render_to_response
from django.http import HttpResponse
from webconf.blog.models import Post
def single(request, year, month, day, slug):
post = Post.objects.get(slug=slug)
return render_to_response('single.html',
{'post': post, })
urlpatterns = patterns('',
('^$', webconf.blog.index),
('^/archives/$', webconf.blog.archives),
('^/(\d{4})(\d{2})(\d{2})/(?P<slug>\w+)/$',
webconf.blog.single),
('^/json/(\d{4})(\d{2})(\d{2})/(?P<slug>\w+)/$',
webconf.blog.json_single),
)
from django.core.serializers import serialize
def json_single(request, year, month, day, slug):
post = Post.objects.get(slug=slug)
json = serialize('json', post)
return HttpResponse(json,
mimetype='application/json')
YAHOO.util.Connect.asyncRequest('GET',
'/json/20070331/webconf/', callback);
urlpatterns = patterns('',
('^$', webconf.blog.index),
('^/archives/$', webconf.blog.archives),
('^/(\d{4})(\d{2})(\d{2})/(?P<slug>\w+)/$',
webconf.blog.single),
('^/(html|json|xml)/(\d{4}) \
(\d{2})(\d{2})/(?P<slug>\w+)/$',
webconf.blog.single),
)
from django.core.serializers import serialize
def single(request, output, year, month, day, slug):
post = Post.objects.get(slug=slug)
if ('html' != output):
output = serialize(output, post)
return HttpResponse(output,
mimetype='application/%s' % output)
return render_to_response('single.html',
{'post': post, })
A GWT bemutatása.
Akkor kapcsoljuk őket össze.
import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONException; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONParser; import com.google.gwt.json.client.JSONString; import com.google.gwt.json.client.JSONValue; import com.google.gwt.user.client.HTTPRequest; import com.google.gwt.user.client.ResponseTextHandler;
class JSONResHandler implements ResponseTextHandler {
public void onCompletion(String responseText) {
try {
JSONValue json = JSONParser.parse(responseText);
displayJSONObject(json);
} catch (JSONException e) {
displayError(responseText);
}
}
class HyperlinkClickListener implements ClickListener {
public void onClick(Widget sender) {
String URL = sender.getRelativeURL();
doAsync(URL);
}
}
private void doAsync(String URL) {
HTTPRequest.asyncGet('http://srv/' + URL + '/',
new JSONResHandler());
}
