Recentemente voltei minhas atenções para a biblioteca javascript ExtJs. O projeto/sistema que venho trabalhando desde outubro de 2009 passou por várias mudanças e uma coisa que eu estava achando ruim era justamente a user interface, afinal não sou um designer
Conversando com o cliente mostrei a biblioteca, expliquei suas vantagens e tive aprovação para refazer a interface. A primeira dúvida era como integrar a chamadas ajax com o Django, já que o mesmo não tem suporte nativo e como serializar objetos de forma flexível. O Django possui um sistema de serialização para os formatos mais conhecidos, mas a forma como os objetos são serializados não me agrada, sendo assim comecei a procurar por alternativas.
Existem poucas alternativas de integração entre Python/ExtJs, das alternativas que testei foram o ExtDirect-Django e Piston.
No final das contas acabei criando uma classe bem simples para serializar objetos de acordo com a minha necessidade, até agora vem funcionando bem e quem quiser melhorar o código fique a vontade
Arquivo json.py
# -*- coding:utf-8 -*-
from django.http import HttpResponse
from django.core import serializers
from django.utils import simplejson
from django.utils.encoding import smart_unicode
# ********************************************
def ext_date(d, date_format=1):
"""
Renderizar Datetime no formato para ExtJs
"""
if date_format==1:
return d.strftime("%m/%d/%Y")
elif date_format==2:
return d.strftime("%d/%m/%Y")
# ********************************************
class JsonResponse(HttpResponse):
"""
Renderizar Dicionrario Python para formato JSON
"""
def __init__(self, params={}):
HttpResponse.__init__(self, content=simplejson.dumps(params), mimetype='application/json')
# ********************************************
class JsonModelResponse(HttpResponse):
"""
Renderizar Model para formato JSON
"""
def __init__(self, queryset, **options):
excludes = options.get('excludes')
date_format = options.get('date_format')
content = {'success': True}
fields, many_to_many, foreignkeys = {},{},{}
opts = queryset._meta # Extrai informação do Model
# colunas
for c in opts.fields:
if excludes is not None:
if c.name in excludes:
continue
if c.__class__.__name__ == 'DateTimeField':
if date_format is not None:
fields.update({c.name: ext_date(getattr(queryset, c.attname), date_format=date_format)})
else:
fields.update({c.name: ext_date(getattr(queryset, c.attname))})
elif c.__class__.__name__ == 'DecimalField':
fields.update({c.name: str(getattr(queryset, c.attname))})
elif c.__class__.__name__ == 'ForeignKey':
pk = getattr(queryset, c.attname)
# Usa o metodo smart_unicode para serializer um objeto model
val = smart_unicode(getattr(queryset, c.name), strings_only=True)
foreignkeys.update({c.name: [pk,val]})
else:
fields.update({c.name: getattr(queryset, c.attname)})
# relaciomentos
for c in opts.many_to_many:
models = c.value_from_object(queryset) # Extrair models da lista
many_to_many.update({c.name: [[{m.name:getattr(model, m.name)} for m in model._meta.fields] for model in models]})
# atualiza dict
content.update({'data': fields, 'foreignkeys': foreignkeys, 'many_to_many': many_to_many})
# retorna a reposta no formato json
HttpResponse.__init__(self, content=simplejson.dumps(content), mimetype='application/json')
# ********************************************
class JsonSuccess(HttpResponse):
"""
Resposta JSON para requests efetuados com sucesso
"""
def __init__(self, params={}):
content = {'success':True}
content.update(params)
HttpResponse.__init__(self, content=simplejson.dumps(content), mimetype='application/json')
# ********************************************
class JsonFailure(HttpResponse):
"""
Resposta JSON para requests efetuados com falha
"""
def __init__(self, params={}):
content = {'success':False}
content.update(params)
HttpResponse.__init__(self, content=simplejson.dumps(content), mimetype='application/json')
A integração fica bem mais simples agora, veja um pequeno exemplo de uma chamada Ajax.
Ext.onReady({
Ext.Ajax.request({
method:'GET',
url:'/usuarios/show/1/'
});
});
No lado do servidor nossa view faz a utilização do módulo json que criamos acima e devolve para o client no formato Json. Observe que na resposta não quero se seja serializado o campo password na resposta.
from utils import json
from django.contrib.auth.models import User
def show(request,id):
qs = User.objects.get(pk=id)
return json.JsonModelResponse(qs, excludes=('password',))
Observando a resposta do servidor pelo Firebug, temos o seguinte:

Interessante não?
One Comment
Olá Samir !
Boa sua solução.. realmente é meio chato serializar os objetos Model do Django com o simplejson.. não funciona direito ! hehehe
Tive que me virar tb…
Post a Comment