Formulari compost a Django
Escrit per Aaloy a 23 de November , 2008 a les 7:48 p.m.
Get the Englist translation of this post at: Gencat
Obtén la traducción al castellano de este post en: Gencat
Django té un sistema de tractament de formularis molt bo. Ens permet per una banda la reutilització de codi, ja que separa el que és la definició del formulari i la seva validació de la part de presentació.
La validació de la informació és d'allò més interessant, ja que assegura que si un camp del formulari l'hem definit com a sencer, el valor de la variable que obtindrem serà un sencer, o en cas contrari hi haurà un error de validació.
Per tot això, la idea és utilitzar el formularis de Django sempre que sigui possible i reutilitzar tot el que tinguem.
El problema es presenta quan en una plana ens n'adonam que necessitam dos formularis, no hi ha cap exemple de com fer-ho a la documentació. Veurem que una vegada solucionat el problema és tant obvi i simple que efectivament no importa documentar-ho, encara que estaria bé :)
Per a aquest exemple he posat el codi al repositori d'appfusedjango
Anem per feina
La idea és ben senzilla, crearem dos formularis i els farem servir a la nostra vista. Per a facilitar-no les coses, podem posar els dos formularis dins una llista de manera que per muntar la plana sols haurem de recorre la llista de formularis que li passam.
A l'exemple he creat dos formularis LoginForm i ContactForm, que es generaran a two_forms.html
def two_forms(request):
if request.method == 'POST':
contact_form = ContactForm(request.POST)
login_form = LoginForm(request.POST)
if login_form.is_valid() and contact_form.is_valid():
# do whatever you need as everything is valid
return HttpResponseRedirect('/thanks/')
else:
contact_form = ContactForm()
login_form = LoginForm()
forms = [contact_form, login_form]
return render_to_response('two_forms.html', {'forms': forms})
Com podem veure el funcionament és el mateix que en el cas d'un formulari normal, sols que hem crear-ne dos (o els que vulguem) i anar cridant al mètode is_valid per fer les validacions.
Això funciona perquè cada formulari agafa del post sols les dades que coincideixen amb els camps que té definits i perquè a l'hora de muntar la plana Django mira si el formulari té errors (la validació es fa tant cridant a is_valid com accedint als errors), d'altra manera i donat que Python fa servir l'avaluació curta de l'and, no tindríem els errors del segon formulari si el primer ja no validàs. Això explica el perquè hi ha aquesta doble via de llançar la validació a Django.
I això ens duu de manera natural a la següent qüestió, què passa si als formularis hi ha camps amb al mateix nom?
Doncs que Django no serà capaç d'esbrinar a quin camp correspon cada cosa in ens trobarem amb un petit problema.
Però tranquils, això està controlat, basta afegir un prefix que sigui únic per a cada formulari. Aquest prefix s'afegirà al nom dels camps que es generen per a l'HTML i d'aquesta manera en recuperar la informació Django sabrà quin camp correspon a cada formulari.
Hem de tenir cura d'assignar el prefixe tant a la part del GET com a la part de POST de la funció.
I això és tot, fàcil i net!
Observacions finals
A l'exemple de tres formularis amb el mateix nom he deixat codi de depuració, el import ipdb; ipdb.set_trace(), ho podeu llevar, levar sols la i del ipdb o bé instal·lar el ipdb, un depurador un poc més potent que el pdb de tota la vida i amb ressaltat de sintaxis.
0 comentaris, 0 trackbacks (URL) , Tags: Python Django
Netbeans IDE 6.5 edició Python
Escrit per Aaloy a 22 de November , 2008 a les 11:51 a.m.
Fa no res ha sortit l'edició Early Accés de Netbeans per Python.
L'IDE integra un editor amb autocompletat de codi, depuració integrada, integració de subversion i tot el que un normalment pot esperar d'un entorn avançat de programació.
En la documentació he vist que hi ha una branca per Django, però encara no he trobat com accedir-hi. Tanmateix no té molta importància ara per ara, ja que si és un bon editor per Python ho serà per editar projectes Django.
En l'execució damunt el PPC amb la màquina virtual IBM JDK6, funciona acceptablement bé, però he tingut que variar alguns dels paràmetres d'inici per a que l'entorn no s'arrossegàs tant. Res de nou, per Ecipse també ho vaig fer, i la impressió general és que llevat els casos en que a la màquina virtual li pega per consumir el 99% de les dues CPUs, l'entorn es comporta molt bé.
El paràmetres de tunejat:
-J-Xmx356m
-J-Xverify:none
-J-XX:CompileThreshold=100
-J-XX:PermSize=64m
-J-XX:MaxPermSize=96m
-J-Djava.net.preferIPv4Stack=true
Aspectes destacats
Entorn de feina: net, molt net. Aprofita molt l'espai de treball i es deixa un gran espai per a l'editor.
El completat de codi és del milloret que he vist. A més han aconseguit extreure la documentació i presentar-la de manera poc intrussiva i elegant.
Possibilitat de crear plantilles. És una de les coses que faig amb Vim i que molts editors tenen, però que no acaben de funcionar tan bé com les de Vim. Netbeans ho fa. He portat algunes de les plantilles de Vim sense problemes.
Navegació entre objectes pitjant amb la tecla Ctrl damunt l'objecte. És un de les coses que més m'agraden d'Eclipse per Java i Netbeans també ho ha incorporat a Python.
Neteja de imports innecessaris. Ens deixa el codi més net.
Tecles ràpides per gairebé totes les opcions. Per mi és important que allò que faig habitualment permeti ser executat sense tenir que llevar les mans del teclat.
Possibilitat de crear les nostres pròpies plantilles.
L'eina de gestió de diferències entre fitxers manté el l'acoloriment de sintaxi. Una gran millora respecte a tot el que hi ha. És una eina fantàstica.
Punts a millorar
L'autocompletat té un preu: l'inici del programa és lent ja que parseja tot el que troba. Si teniu l'opció del la finestra de tasques activada la cosa pot arribar a ser insuportable. Afortunadament si posam que sols ens mostri les tasques de l'editor actiu la cosa millora. Tot i així crec que falta algun tipus de configuració per poder definir per projecte les llibreries que s'utilitzaran i les que no per agilitar-ne el parseig i evitar que algunes vegades a l'autocompletat surtin cents d'opcions que no tenen res a veure amb el projecte.
La integració amb subversion és bona, però la interfície de selecció del que s'ha de pujar i del que no és molt farragosa, ja que s'ha de seleccionar element a element amb un desplegable.
Pareix haver hi un error quan es selecciona una plantilla, ja que sols te deixa triar les de Python i Others. Es posa tot allà dintre i ja està, però sorprèn.
Refactorització. La que té Eric4 amb Rope o la de pyDev mateix permeten més opcions.
Hi ha un bon grapat de coses que vull explorar com són les macros, la inserció de codi i mirar més a fons el comportament de les plantilles, crec que se n'hi pot treure molt de suc.
Com a conclusió dir que m'ha agradat molt aquest entorn. Potser estic molt condicionat a que ha funcionat força bé en el PPC, però en la meva opinió és un entorn fantàstic per al desenvolupament de Python en general i de projectes Django en particular.
El faré servir una temporada, sols hi duc dos dies, a veure si tot confirma ser tant bo com sembla i puc trobar com instal·lar la branca per Django. Això sí, el vim seguirà essent un dels meus principals entorns de desenvolupament: quan un ha de fer modificacions de codi ràpidament o treballar per ssh no hi ha res millor. Sempre serà o bé una eina principal o complementària. Sempre és bo tenir dos editors de capçalera.
3 comentaris, 0 trackbacks (URL) , Tags: Python Django
El django-admin no és per fer aplicacions d'usuari final
Escrit per Aaloy a 15 de November , 2008 a les 10:24 a.m.
Quan la gent dóna les seves primeres passes amb Django sovint queda enlluernada pel django-admin, una aplicació Django que ens permet definir un gestor de les nostres aplicacions, de manera que podem gestionar els usuaris, donar-hi permisos, gestionar les bases de dades, etc.
Hi ha que dir que l'aplicació està molt ben feta i es pot configurar moltíssim: indicar quins camps s'han de visualitzar, per quins camps es cercaran, fins i tot posar-hi javascript o modificar-ne l'aparença per a que la nostra aplicació faci el que nosaltres volem.
Aquesta facilitat però, té un perill, la gent té tendència a pensar que Django serveix per fer aplicacions web amb l'admin, que la seva aplicació ha de ser l'admin, així que recordem-ho:
El django-admin no és per fer aplicacions d'usuari final
Django admin fa molta màgia per dintre i aquesta màgia es basa en convencions que s'apliquen als models i a la definició del ModelAdmin, i aquestes convencions fan que per una part pugem tenir un gestor per a la nostra aplicació en quatre potades, però per altra, que si volem fer alguna cosa que surti del que està definit i establert ens durà molta feina.
La millor manera d'encarar-ho és tenir molt clar per a què serveix l'admin i per a què no:
Manteniment de les nostres taules de configuració i mestres? sí. Normalment ens anirà fantàstic per això i a meś ho podem tenir molt ràpidament. És ideal en les primeres etapes del desenvolupament, ja que es pot donar a l'usuari per a que carregui dades de prova i ja veu com pot funcionar l'aplicació.
Com a gestor web de la nostra base de dades? També anirà molt bé. Podem mapejar les taules i els camps que volem administrar, fer cerques, filtrar, editar i esborrar.
Com a eina d'usuari final per a que pugui configurar l'aplicació? Sí, si aquesta sols implica operacions senzilles, per exemple l'edició d'una plana web, afegir registres a una taula, etc. Podem definir quines taules pot tocar cada usuari i definir-ne perfils.
Com a eina d'usuari final on l'aplicació té molta lògica de negoci o bé un fluxe complex. NO. Millor començar un gestor pel nostre compte. Fer formularis CRUD amb Django és molt senzill i encara que pareix que dupliquem el que hi ha al django-admin, aquesta feina extra es veurà compensada a l'hora de definir els fluxs més complexos, ja que tindrem tota la potència de Python i Django al nostre abast i no estarem limitats a les convencions i funcionament del Django admin.
Les coses funcionen molt millor quan s'utilitzen per allò que estan pensades.
0 comentaris, 0 trackbacks (URL) , Tags: Python Django
Rapid GUI Programming with Python and Qt
Escrit per Aaloy a 10 de November , 2008 a les 12:30 a.m.
El divendres vaig rebre un nou llibre:
Rapid GUI Programming with Python and Qt
Editorial Prentice Hall
Autor: Mark Summerfield
ISBN: 978-0-13-235418-9
Es tracta d'un manual de programació per al desenvolupament d'aplicacions amb Python i les Qt.
Me l'he estat fullejant i la veritat és que sols amb la qualitat de l'edició el llibre promet.
El primers capítols duen una petita introducció a Python, que segurament servirà a la gent que s'atraqui al món del la programació d'aplicacions d'escriptori portables, cercant quelcom més senzill de fer anar que la programació en C++.
L'estructura s'orienta per temes, on es van construint aplicacions de diferents nivells de complexitat i es complementa el tema amb tot un seguit d'exercicis per a que el lector faci feina pel seu compte.
Els que ens dedicam fonamentalment a la programació web, sovint tenim tendència a pensar que l'escriptori clàssic no té sentit, i això no és cert. Ara per ara encara hi ha força aplicacions i entorns on una aplicació d'escriptori pot solucionar millor els problemes al nostre client que una aplicació web. Poder oferir una solució feta amb Python amb una llibreria com Qt4 (no oblidem tampoc les WxPython) sens dubte ens serà de profit per ambdues parts.
0 comentaris, 0 trackbacks (URL) , Tags: Llibres i revistes Python
Senyals a Django
Escrit per Aaloy a 03 de November , 2008 a les 8:35 p.m.
El mecanisme de senyalització de Django ens permet desacoblar les nostres aplicacions, ja que permet notificar d'accions que es produeixen a tot una sèrie de receptors o subscriptors d'aquestes senyals.
Podem distingir dos tipus de senyals a Django:
Les senyals que venen predefinides a bastiment i que podem trobar a la documentacio de Django. En aquest cas Django se n'encarrega de llançar l'avís de que una acció concreta s'ha produït i nosaltres com a programadors podem generar codi per tal de subscriure'ns a aquest tipus de missatges i disposar-ho tot per a que s'executi el codi que ha de respondre a aquestes accions.
Les senyals definides per l'usuari. Es un cas més general que l'anterior. Django ens permet definir les nostres pròpies senyals i enviar-les. En aquest cas doncs, podem definir tant la senyal com el tractament que se'n faci.
Escoltant senyals
Per a escoltar una senyal necessitam fer dues coses:
Definir la funció que rebrà la senyal amb el codi que s'ha d'executar.
Connectar la funció amb la senyal, és a dir subscriure's a la senyal.
Les funcions que haurem de definir han de ser de la forma:
def nom_funcio (sender, kwargs): "Aqui va la documentacio" # aqui el codi pass
Hem de tenir en compte que el nombre d'arguments que pot transmetre una senyal per definició pot canviar en qualsevol moment. Els arguments es passen per nom, i la nostra funció ha d'estar preparada per gestionar aquest possible canvi d'arguments.
Per a connectar la senyal amb la nostra funció importarem la senyal a la que ens vulguem subscriure i ens hi connectarem amb el mètode connect de la pròpia senyal.
Per exemple per connectar-nos a la senyal que s'emet quan una petició http ha acabat bastaria fer:
from django.core.signals import request_finished request_finished.connect(nom_funcio)
Les senyals tenen un paràmetre per defecte, el sender, que ens permet subscriure'ns sols a aquelles senyals que provenguin d'instàncies d'una classe determinada.
Definint les nostres senyals
Per a definir les nostres senyals hem fer dos passos:
Definir la senyal i els arguments que passarà
Allà on ens interessi enviar la senyal amb els arguments que hem definit
Pel primer pas basta importar django.dispatch i crear una instància de Signal amb els paràmetres que hem definit.
import django.dispatch pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
Enviar la senyal és encara més senzill, basta cridar al mètode send amb els paràmetres que hem definit, sense oblidar-nos d'establir la variable sender amb l'objecte que ha enviat la senyal.
Suposem que volem que el sistema ens avisi automàticament cada cop que algú esborra un usuari de la base de dades.
Per a mostrar-ho farem ús del senyal pre_delete que es troba a django.db.models.signals. Per al registre crearem una taula a la BD que guardarà l'usuari que se va esborrar i el seu nom.
La senal pre_delete s'envia quan s'entra dins el mètode delete del model, com a arguments té el sender que és la classe que envia la senyal i instance que recull l'objecte que s'eliminarà de la base de dades.
Nosaltres ens volem registrar sols a les senyals que impliquin eliminar usuaris de l'aplicació, així que sols ens subscriurem a les senyals que provenguin de django.contrib.auth.models.User
El nostre model seria
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Autor: aaloy from django.db import models from django.contrib.auth.models import User from django.db.models.signals import pre_delete class Eliminat(models.Model): user = models.CharField(max_length=30) created = models.DateTimeField(editable=False, auto_now_add=True, blank=False, db_index = True) def __unicode__(self): return self.user def registra(sender, **kwargs): instancia = kwargs['instance'] usuari = Eliminat(user=instancia.username) usuari.save() pre_delete.connect(registra, sender=User)
Per a veure com podem utilitzar les nostres pròpies senyals, crearem una senyal que registrarla la IP i el nom de la vista.
Per això crearem una nova classe, per exemple LogIp, que mantindrà el registre i connectarem el senyal amb la funció registre_ip
Hem de tenir en compte que es un exemple acadèmic, té poc sentit fe aquest tipus de coses, és a dir, definir una senyal dins el mateix model i enviant-la a la vista. Té molt més sentit que el senyal s'envii en resposta a una acció dins el propi model o a una acció particular de la vista i que una aplicació externa s'hi subscrigui.
class LogIp (models.Model): "Logs the ips and calling functions" name = models.CharField(max_length= 200) ip = models.IPAddressField() created = models.DateTimeField(editable=False, auto_now_add=True, blank=False, db_index = True) in_view = django.dispatch.Signal(providing_args=['ip', 'name']) def registra_ip(sender, **kwargs): ip = kwargs['ip'] name = kwargs['name'] log = LogIp(name= name, ip=ip) log.save() in_view.connect(registra_ip)
in_view és la nostra senyal, com a paràmetres hem posat ip i name, això vol dir que la funció que es registri com a escoltadora els pot fer servir i ha de ser capaç de admetre'ls. Per una altra banda també ens diu que allà on enviem la senyal amb el send haurem de proporcionar també aquests paràmetres.
Si llançam el senyal a la vista quedaria com
def list(request): "Lists the deleted users" deleted = Eliminat.objects.all() in_view.send(sender=chivato.views.list, ip=request.META['REMOTE_ADDR'], name=request.get_full_path()) return render_to_response('list.html', {'deleted':deleted})
Amb això cada cop que algú des de el seu navegador accedeixi a la funció quedarà registrada la url d'accés i la seva ip.
Tot el codi font amb un projecte complet llest per funcionar, sols heu de canviar las rutes al properties.py a appfuse o directament
svn checkout http://appfusedjango.googlecode.com/svn/trunk/signals
0 comentaris, 0 trackbacks (URL) , Tags: Python Django
The myths of innovation
Escrit per Aaloy a 02 de November , 2008 a les 7:22 p.m.
Ahir vaig acabar de llegir the myths of innovation, d'Scott Berkun, que havia rebut via Amazon en la remesa d'agost.
Amb aquest llibre he acabat la remesa d'agost, però encara me queden altres lectures informàtiques, que eren menys interessants que aquestes i que encara no he acabat, així que supòs que podré resistir fins que arribi la nova remesa que ja he comanat.
Del llibre dir que m'ha agradat molt, és un assaig molt lúcid i interessant del que significa la innovació, de com s'hi arriba i de l'impacte que té tant en els innovadors com en la societat.
El llibre desfà molts mites, el de la serendipia per exemple n'és un. Estam acostumats a que ens diguin que molts grans descobriments de la humanitat s'han fet per casualitat, com si un dia el descobridor s'aixecàs veies la cosa i au, ja tenim el descobriment.
La innovació i el seu èxit, segons ens explica Berkun són una combinació de circumstàncies, factors socials, talent de l'innovador i sobre tot de feina molta feina, tant per adonar-se de que allò és una cosa nova, com per a posar-la en pràctica.
Lectura recomanada!
0 comentaris, 0 trackbacks (URL) , Tags: Llibres i revistes