Este año una de las metas propuestas es mejorar nuestro nivel de código, el anterior año estuvimos mas atentos a las practicas ágiles pero mas centrados en la parte del management, pero sin duda después de haberme iniciado como QA, luego hacer de developer y entrar al management, me doy cuenta que el management tienes mas allá de leer o tomar cursos es vivirlo y aplicarlo en casos reales y uno no puede enseñar buenas prácticas si nos la hace, en fin algo que siempre estuve buscando fue un grupo con el cual compartir y aprender experiencias y programar juntos, se que tuve un año muy flojo programando pero este año lo dedicaremos entero a mejorar nuestro código.
Aca les paso el resumen de nuestra primera reunión, cabe resaltar que el grupo fue iniciativa de rolando.
Bueno, nos reunimos entre antonio, rolando, jimmy y sergio (yo).
Hablamos de varias cosas y entre las que me acuerdo:
Se hablo sobre dos approaches para organizar el barcamp,
uno es “más ceremonial”, haciendo cartas para solicitar
ambientes, convocando estudiantes, poniendo fechas
con mucha anticipación etc.
Y la otra más espontánea, se propone una fecha, un problema
y nos juntamos para programar.
Se opto por la última, por que la primera require más organización,
etc. Que por ahora no es momento.
Bajo esa premisa se nos ocurrió realizar la primera sesión
aprovechando el Barcamp, este sábado 30 en la tarde
2-4pm
Hable con la organización y nos pueden habilitar un ambiente.
Nos encargamos de la portatil, y esta la opción de un data display.
Antonio va a realizar una charla pequeña en la mañana para explicar
de que trata el coding dojo e invitar a la gente.
Sobre el problema vamos a resolver este, que no es muy complicado
http://acm.uva.es/p/v101/10189.html
Sobre el lenguaje, se barajeo la opción de c, java pero se opto
por python, más que todo por los conocimientos frescos
sobre los unittest.
Para tomar en cuenta, al escoger el lenguaje hay que tomar en cuenta
que extrictamente se aplica TDD, ya sea con unittest u otro framework,
o puros asserts
=== En resumen ===
Lugar: Barcamp – Centro Manuela Gandarillas – Inmediaciones
América/Liberator
Fecha: sábado 30/02
Hora: 14:00 – 16:00
Lenguage: python
Problema: http://acm.uva.es/p/v101/10189.html
Confirmados:
- Sergio
- Antonio
- Jimmy
- Rolando
=== /resumen ===
No hablamos sobre el estilo, pero supongo que aplicaremos randori
(rotación piloto/copiloto)
Luego tambien comentamos de ponernos más exquisitos y probar lenguajes nuevos:
clojure, erlang, scala, haskell, etc.
Y tambien de tratar hacer una sesión por semana, variando language/problema.
El lenguaje y problema pueden ser sometidos a votación, pero si entre dos o tres
se animan a convocar una sesión no hay problema, los demás apoyamos,
lo que menos queremos es burocracia
Git es uno de los mejores versionadores distribuidos, si usas github pero quieres tener tu propio repositorio en tu casa o trabajo entonces esta es una simple solucion, que no te toma mas de unos minutos, esta misma configuracion la he probado en dreamhost y funciona de la misma manera, de echo deberia funcionar en cualquier host que tengas. Si quieres ademas poder publicarlo mediante http, entonces una muy buena opcion gitweb. Gitosis es tambien otra opcion que tienes, que es muy parecido pero para algun proyecto simple creo que esto es suficiente.
1. Configuración del Servidor git
El único requisito es tener instalado git:
$ sudo apt-get install git-core
nota: El servidor esta configurado e instalado en django-server que tiene la IP 192.168.0.139, el usuario es django-server con password *****.
2. Configuración del Cliente git
Primero debemos generar el conjunto de llaves RSA:
$ ssh-keygen -t rsa
Luego debemos registrar nuestra llave publica en el servidor, dentro de las llaves autorizadas de ssh, como sigue:
$ cat .ssh/id_rsa.pub | ssh django-server@192.168.0.139 ‘cat >> .ssh/authorized_keys’
En caso de no tener git instalarlo:
$ sudo apt-get install git-core
Crear el archivo initrepo con el siguiente contenido:
$ vim initrepo
DOMAIN=django-server@192.168.0.139
ssh $DOMAIN ‘mkdir -p ~/git/’$1′.git && cd ~/git/’$1′.git && git –bare init’
mkdir $1
cd $1
git init
git remote add origin ssh://$DOMAIN/~/git/$1.git
touch .gitignore
git add .
git commit -m ‘Created new repo’
git push origin master
echo “
[branch \"master\"]
remote = origin
merge = refs/heads/master” >>.git/config
echo “Your new git repo ‘$1′ is ready and initialized at $DOMAIN/~/git/$1.git”
Asignarle los permisos:
$ sudo chmod a+x initrepo
Para iniciar un repositorio nuevo en la maquina remota solo es necesario ejecutar initrepo y pasarle como parámetro el nombre del repositorio:
$ ./initrepo test01
Inmediatamente veras una salida como esta:
Reinitialized existing Git repository in /home/django-server/git/test01.git/
mkdir: cannot create directory `test01′: File exists
Initialized empty Git repository in .git/
Created initial commit cccf28a: Created new repo
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 .gitignore
Counting objects: 3, done.
Writing objects: 100% (3/3), 219 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://django-server@192.168.0.139/~/git/test01.git
* [new branch] master -> master
Your new git repo ‘test01′ is ready and initialized at django-server@192.168.0.139/~/git/test01.git
Veras que en tu propia maquina tendrás la carpeta test01, ingresa y ya puedes empezar a hacer cambios y propagarlos en el servidor haciendo git push.
3. Obtener una copia de un repositorio remoto git y trabajar sobre el mismo
Para poder obtener una copia de un repositorio remoto primero deberá registrar su llave publica en el servidor remoto.
git clone ssh://django-server@192.168.0.139/~/git/test01.git
Luego puedes hacer cambios y replicarlos en el repositorio remoto con git push.
Referencias:
http://autopragmatic.com/2008/01/26/hosting-a-git-repository-on-dreamhost/
http://casperfabricius.com/site/2008/09/21/keeping-git-repositories-on-dreamhost-using-ssh/
http://madduck.net/blog/2007.07.11:publishing-git-repositories/
http://batterypowered.wordpress.com/2008/07/04/deploying-a-git-repository-server-in-ubuntu/
http://www.urbanpuddle.com/articles/2008/07/11/installing-git-on-a-server-ubuntu-or-debian
http://mechanicalrobotfish.com/posts/119-installing-git-server-using-gitosis
Es un resumen breve para configurar nuestro servidor apache con mod_wsgi, memcache y nginx, el cual lo he recopilado de varios sitios, el cual espero pueda ser de ayuda y tambien pueda permitirnos a abrir debatos en lo que se refiere a las mejores practicas para configurar tus host para aplicaciones django.
Por que mod_wsgi y no mod_apache, puedes encontrar en este resumen mas detalles en los siguientes links:
- http://code.google.com/p/modwsgi/wiki/PerformanceEstimates
- http://code.google.com/p/modwsgi/wiki/FrequentlyAskedQuestions
- http://blog.webfaction.com/django-setup-improvements
Primero instalamos todos los paquetes requeridos:
$ sudo apt-get install subversion gcc curl
$ sudo apt-get install build-essential python-dev python-setuptools
$ sudo apt-get install python-egenix-mxdatetime memcached postfix
Para configurar memcache, necesitamos realizar dos pasos, el primero será inicializar memcache:
$ sudo memcached -u www-data -p 11211 -m 32 -d
(Inicializa memcached bajo el usuario www-data con 32 megabytes de ram)
Ahora necesitaremos construir el cmemcache, para ello obtenemos la siguiente librería:
$ sudo apt-get install libmemcache-dev
Ahora obtenemos el cmemcache y haremos un build del mismo:
$ wget http://gijsbert.org/downloads/cmemcache/cmemcache-0.95.tar.bz2
$ tar -xjvf cmemcache-0.95.tar.bz2
$ cd cmemcache-0.95
$ sudo python setup.py install
Instalación y configuración de Nginx
Primero debemos instalar nginx:
$ sudo apt-get install nginx
Luego inicializar nginx:
$ sudo /etc/init.d/nginx start
Podemos probarlo realizando curl 127.0.0.1 que nos devolverá una pagina html con titulo: Welcome to nginx!!
A continuación editamos la configuración básica de nginx, actualizando los siguientes datos:
$ sudo vim /etc/nginx/nginx.conf
worker_processes 4; #4 indica que el servidor usa 4 procesadores
tcp_nopush on; # activar esta línea
keepalive_timeout 2;
gzip on;
gzip_comp_level 2;
gzip_proxied any;
gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
Luego debemos añadir un nuevo archivo de configuración llamado proxy.conf que deberá contener lo siguiente:
$ sudo vim /etc/nginx/proxy.conf
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
Puesto que nginx usa el Puerto 80 debemos cambiar la configuración de nuestro apache para que use el puerto 8080, para ello modificamos el archivo /etc/apache2/ports.conf y remplazamos el 80 por 8080.
Puesto que nginx no soporta la opción keepAlive debemos desactivar la misma en nuestro apache, para ello editamos el archivo /etc/apache2/apache2.conf y ponemos: KeepAlive off.
Ahora nos toca crear la estructura de directorios para nuestro dominio:
$ mkdir –p /home/<username>/webapps/<midominio>/{public,private,log,backup}
Para habilitar nginx en nuestro dominio debemos añadir nuestro dominio a los sitios habilitados y disponibles en nginx, para ello debemos añadir el siguiente archivo:
$ sudo vim /etc/nginx/sites-available/<midominio>
Cuyo contenido debería tener algo parecido a:
server {
listen 80;
server_name <midominio> www.<midominio>;
access_log /home/<username>/webapps/<midominio>/log/access.log;
error_log /home/<username>/webapps/<midominio>/log/error.log;
# main
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real_IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
location /media/ {
root /home/<username>/webapps/<midominio>/public/;
}
}
Luego debemos crear un link del mismo archivo a sites-enabled:
$ sudo ln -s /etc/nginx/sites-available/<midominio> /etc/nginx/sites-enabled/<midominio>
$ sudo /etc/init.d/nginx restart
Para probar nginx, primero añadimos nuestro dominio al archivo de host usando nuestra ip.
$ sudo vim /etc/hosts
Dicho archivo debería verse algo asi:
127.0.0.1 localhost
<mi ip> www.<midominio>
Luego en un browser ingresar a tu dominio y debera aparecer la pagina de error de nginx.
Instalar y Configurar mod_wsgi, con apache, nginx
Obtenemos mod_wsgi para nuestro servidor apache:
sudo apt-get install libapache2-mod-wsgi apache2-mpm-worker apache2-threaded-dev
En primera instancia debemos deshabilitar los sitios por defecto de apache:
$ sudo a2dissite 000-default
Asignamos los permisos correctamente:
$ sudo usermod -a -G www-data <username>
- Aseguramos que el directorio /home/<username>/webapps sea de <username> y que además este en el grupo www-data:
$ sudo chgrp -R www-data /home/<username>/
Nos aseguramos que todos los archivos nuevos de nuestro directorio webapps, heredaran los permisos:
$ sudo chmod -R 2750 /home/<username>/webapps
Otorgar permisos de escritura al usuario apache en el directorio privado de nuestro dominio:
$ sudo chmod -R 2770 /home/<username>/webapps/<midominio>/private
Obtener tu proyecto django y colocarlo dentro del directorio /home/<username>/webapps/<midominio>/
A continuación creamos el archivo wsgi:
vim /home/<username>/webapps/<midominio>/miproyecto.wsgi
El cual tendrá el siguiente contenido:
import os, sys
sys.stdout = sys.stderr
if ‘/home/<username>/webapps/<midominio>’ not in sys.path:
sys.path.append(‘/home/<username>/webapps/<midominio>’)
if ‘/home/<username>/webapps/<midominio>/<miproyecto>’ not in sys.path:
sys.path.append(‘/home/<username>/webapps/<midominio>/<miproyecto>’)
os.environ['DJANGO_SETTINGS_MODULE'] = ‘<miproyecto>.settings’
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
Por ultimo lo que nos toca es configurar el virtual host en el apache.
$ sudo vim /etc/apache2/sites-available/<midominio>
<VirtualHost *:8080>
ServerName www.<midominio>
ServerAlias <midominio>
<Directory /home/<username>/webapps/<midominio>/<miproyecto>/>
Order deny,allow
Allow from all
</Directory>
LogLevel warn
ErrorLog /home/<username>/webapps/<midominio>/log/apache_error.log
CustomLog /home/<username>/webapps/<midominio>/log/apache_access.log combined
WSGIDaemonProcess <midominio> user=www-data group=www-data threads=25
WSGIProcessGroup <midominio>
WSGIScriptAlias / /home/<username>/webapps/<midominio>/<miproyecto>/<miproyecto>.wsgi
</VirtualHost>
Creamos un link del archivo para colocarlo entre los sitios habilitados de apache:
Ln –s /etc/apache2/sites-available/<midominio> /etc/apache2/sites-enable/<midominio>
Por ultimo le decimos a apache que agregue nuestro dominio:
$ sudo a2ensite <midominio>
$ sudo /etc/init.d/apache2 reload
Reiniciamos nuestro apache y listo!! Tenemos nuestro dominio en www.<midominio>
Referencias:
http://articles.slicehost.com/2008/5/16/ubuntu-hardy-nginx-virtual-hosts
http://www.meppum.com/2009/jan/17/installing-django-ubuntu-intrepid/
http://lethain.com/entry/2007/jul/17/dreamier-dream-server-nginx/
http://lethain.com/entry/2009/feb/13/the-django-and-ubuntu-intrepid-almanac/
Los managers son una interfaz por encima de los modelos de django, que nos permiten realizar consultas sql relacionadas al modelo al cual están relacionados.
Django nos provee para todos los modelos un manager por defecto (objects), el cual nos provee una buena cantidad de consultas en forma de funciones (all, filter, exclude, etc)
Los managers los usamos en dos formas, una para sobreescribir el queryset que viene dado por defecto, y el otro para extender funcionalidad o extender nuestra gama de consultas que podemos realizar al modelo.
Sobreescribiendo el queryset
Cuando? si necesitas que ciertas instancias (tuplas de datos en la BD) no sean mostradas, entonces reducimos los resultados mostrados por el queryset que viene por defecto.
A continuacion escribimos un manager propio, en el cual sobreescribimos el queryset par devolver uno filtrado, que solo me muestre objetos que esten activos.
class CustomManager(models.Manager):
def get_query_set(self):
return super(CustomManager, self).get_query_set().filter(activo=True)
Class Empleado(models.Model):
nombre_completo = models.CharField(max_lenght=100)
activo = models.BooleanField(default=True)
A continuacion existen dos alternativas, la primera es sobreescribir el manager que viene por defecto y es accesido usando el nombre de objects, tambien puedes designarle un otro nombre, pero ya no podras llamar al atributo objects ya que al definir uno propio como se llame, objects ya no es mas disponible a menos que lo definamos explicitamente.
objects = CustomManager()
En el caso definido arriba, objects solo maneja los objetos empleado activos (activo=True), por lo cual:
Empleado.objects.all()
listara todos los empleados activos.
Por otro lado si se desea mantener objects, entonces debemos:
objects = models.Manager()
activos = CustomManager()
De esta manera tenemos:
Empleado.objects.all() que nos lista todos los empleados
Empleado.activos.all() que nos lista todos los empleados activos
El orden como se los define es importante, ya que el default manager, que es invocado por el admin, sera el que primero sea definido.
Lo que se quiere:
Mantener el ítem seleccionado dentro de un dropdown list, después de que el usuario realice un submit, se requiere que el campo seleccionado por el usuario se mantenga seleccionado.
Lo que se nos provee por defecto:
Una vez que el cliente presiona submit, los valores de nuestro formulario son restablecidos a los por defecto (campos en blanco y sin selección).
Solución 1:
Guardar el ítem seleccionado en la sesión del usuario (para mayor seguridad), luego; cada vez que se cree el formulario, verificar si existe en la sesión el ítem seleccionado, si existe: entonces pasarlo dentro de los valores iniciales que tomara nuestro formulario.
Ejemplo:
Usaremos un formulario que permita seleccionar un usuario e ingresar/guardar sus horas de trabajo semanales, y que tambien pueda navegar a través de las semanas pasadas y posteriores, para dicha navegación requeriremos que el empleado seleccionado se mantenga seleccionado.
Dentro de nuestro ModelForm sobreescribimos nuestro init:
def __init__( self, request, *args, **kwargs ):
report = None
if ‘do’ in request.POST:
start_date = parsedate(request.POST['hidden_start_date'])
else:
if request.session.__contains__(‘employee’):
# En esta sección verifico si esta guardado nuestro empleado seleccionado en la sesión, si es así, obtengo el empleado seleccionado.
employee=request.session.get(‘employee’)
report = TimeReport.objects.extra(where=['employee_id=%s', 'company_id=%s', 'start_week_date=%s'], params=[employee, request.user.client.pk, start_date])
# A continuación sobreescribiremos los valores iniciales de nuestro formulario y le agregaremos como valor inicial que este seleccionado el empleado que sacamos de la sesión.
initial = {‘employee’: employee }
initial.update(kwargs.get(‘initial’, dict()))
kwargs['initial'] = initial
super( TimeReportForm, self ).__init__( *args, **kwargs )
Solución 2:
En la vista, verificar si el usuario ha seleccionado un cliente, si es así, crear el formulario y pasarle los valores iniciales (el empleado seleccionado):
if ‘employee’ in request.POST:
form = TimeReportForm(request)
form.initial = {‘employee’: request.POST['employee'] }
En esta segunda solución tan simple, existiría varias ventajas y solo una desventaja,
Ventajas:
Menos código, ya no es necesario guardar y recuperar una variable de sesión y tampoco sera necesario realizar operaciones extras.
Desventaja:
La selección del empleado no se recordara durante la vida de la sesión del usuario como ocurre en la primera solución.
DRY – Dont Repeat Yourself, Django esta pensado en facilitarte muchas necesidades muy comunes.
Muchas veces descuidamos algunos detalles al leer la documentacion o simplemente no la entendemos, Dont Repeat Your Self es algo que debemos aplicar en todo momento, mas aun cuando usamos frameworks como Django, donde siempre existe una forma mas sencilla de hacer las cosas.
En el ejemplo siguiente, sobreescribo la manera de construir un formulario, especificamente: De lo aplicantes quiero que solo se muestren los que han sido seleccionados como empleados, en el campo employee:
class PayRollForm(forms.ModelForm):
def __init__( self, *args, **kwargs ):
super( PayRollForm, self ).__init__( *args, **kwargs )
self.fields['employee'] = forms.ModelChoiceField(queryset = Applicant.employees.all(), label=_(‘Employee’))
class Meta:
model = PayRoll
En la ultima linea sobreescribo el queryset, pasandole un nuevo queryset pero que solo contiene la lista de empleados.
Es asi fue como resolvi la primera vez que empezaba a jugar con django. Despues de leer detenidamente la documentacion y tratando de no perder detalles, encontre que la solucion a mi problema, era tan simple como:
Model PayRoll(models.Model):
employee = models.ForeignKey(Applicant, verbose_name =_(‘Employee’), related_name=’employee_payroll’, limit_choices_to = {‘is_employee’: True})
El atributo limit_choices_to nos permite filtrar los datos a ser mostrados en un campo que recibe llaves extranjeras.
Basto con una linea para resolver mi problema, lo bueno fue que aprendi a sobreescribir mis formularios y a prestar mayor atencion a a los detalles en la documentacion de Django.
Anuncio del lanzamiento de la Segunda Version del Libro Oficial de Django (para la version de Django 1.0)
Adrian Holovaty nos anuncia en su blog del lanzamiento de la Segunda Version del Libro Oficial de Django, el cual ahora no contiene incompatibilidades con la actual version de Django 1.0.
Durante este periodo fue realmente una tragedia para muchos que se iniciaban en Django al no tener a la mano Libros que esten totalmente actualizados de acuerdo al a Version 1.0.
Enlaces de interes:
Adrian en Twitter, nos mantendra informados de los avances.
Los borradores del libro que son gratis y estan en linea.
Realmente fantastico, Corey Haines lleva adelante su tour denominado “Pair-Programming Tour 2008″, lleno de nuevas experiencias y donde hace prevalecer que la experiencia de trabajar en parejas te lleva a aprender y compartir mucho mas que del modo simple y solitario.
Quien es Core Haynes?
Corney Haines, paso el ultimo año casi exclusivamente desarrallonado con Ruby on Rails, antes de ello paso 5 años desarrollando con C#. Y durante los ultimos 4 años ha estado dirigiendo e implementando tecnicas de desarrollo agil, como la programacion en parejas, BDD y TDD.
Actualmente se encuentra sin empleo, pero con algunos ahorros en el bolsillo y con la ayuda de sponsors, ahora lleva adelante este evento, que tambien es parte de lo que pretendia hacer como uno de sus siguientes pasos en su carrera profesional. Obviamente cuando acabe el tour quedara sin dinero practicamente y necesitara conseguir un empleo.
Mas datos del evento:
Core Haines ha creado un blog exclusivo para el evento, Corey Haines’ Pair Programming Tour.
A continuacion una breve lista de las entrevistas con los personajes que tuvo la oportunidad de trabajar en pareja:
- Entrevista con David Chelimsky’s. quien trabaja manteniendo Rspec
- Entrevista con Dave Hoover from Obtiva
- Entrevista con Brian Marick quien trabaj en el libro de Ruby Cocoa book, con quien Corey tuvo la oportunidad de realizar algunos ejercicios de TDD que estaran incluidos en el libro, existen dos charlas con muy buen contenido Parte I y Parte II.
- Entrevista con Eric Meyer, con quien trabajo en Fresnel la interfaz de “Lighthouse bug-tracking system”.
- Entrevista con Micah Martin el fundador de 8th Light en Chicago, 8th Light actualmente se encuentra desarrollando Limelight, el cual es un framework para el desarrollo de interfaces grafica de usuarios GUI.
- Entrevista con Jonathan Branam , autor de Red Sun, una Maquina Virtual en Ruby para flash. Corney tuvo la oportunidad de conocer como Jonathan porta directamente el codigo fuente del MRI a ActionScript.
- Entrevista con Joe O’Brien de Edgecase, en esta ocasion Courney tuvo la oportunidad de trabajar en pares con algunos chicos de Edgecase.
- Entrevista con John Distad de Edgecase
- Entrevista con Craig Muth, quien desarrollo el framework llamado Xiki.
- Entrevista con Jean Jennings Bartik quien fue una de las primeras personas en programar ENIAC.
Fue todo un tour el que lleve adelante en el blog de Corey y fueron muchas las horas que me tomo para ver cada una de las entrevistas, pero sin duda estas experiencias son las que nos enriquecen y las que dificilmente encontraremos en libros, blogs, etc.
Goodbye Pownce, Hello Six Apart, es asi como titula el post que nos recuerda que hoy es el ultimo dia de esta gran aplicacion echa en django, y tal cual lo refleja su creadora leah, ahora junto a mike, seran parte del equipo de ingenieros de Six Apart. Esperemos que pronto tengan nuevas noticias y puedan traernos sorpresas para la gran comunidad de django.
Si quieres seguirlos en esta nueva proeza, podemos encontrar sus blogs en vox:
leahculver.vox.com, Mike en mjmalone.vox.com, y Ariel en arielwaldman.vox.com.
Anuncio oficial de Six Apart, dando la bienvenida al equipo de pownce:
http://www.sixapart.com/blog/2008/12/welcome-pownce-team.html
Django viene con muchas aplicaciones reutilizables directamente añadidas al core o a la version de distribucion, entre una de ellas, de echo la mas utilizada, es la de administracion “django.contrib.admin“.
El admin de django te permite tener una interfaz administrativa para tus modelos, el unico requisito es que las registres, a continuacion recrearemos una pequeña aplicacion llamada todo manager.
Para habilitar el admin, debemos añadirlo a nuestro settings.py
INSTALLED_APPS = (
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.sites’,
‘django.contrib.admin’,
‘todomanager’, # nuestra aplicacion que vamos a crear mas adelante
)
Sobre el proyecto ahora crearemos una nueva aplicacion que se llame todo:
#./admin.py start-app todo
Django nos crea los archivos models.py y views.py por defecto en el nuevo directorio de nuestra aplicacion que lleva el mismo nombre que el que le dimos.
Abrimos el models.py y a continuacion definimos los modelos de nuestra aplicacion:
(archivo: models.py)
from django.db import models
from django.utils.translation import ugettext_lazy as _
# ugettext_lazy es parte de la aplicacion de internacionalizacion de django y viene junto al core de django, el objetivo es que podamos mostrar tanto el contenido como las funcionalidades en varios idiomas, para añadir esta caracteristica usaremos textos traducibles de la forma _(‘texto a ser traducido’).
from django.contrib.auth.models import User
#django nos provee otra aplicacion que maneja la autenticacion, en el todo el modelo User nos servira para representar al dueño.
from datetime import datetime
class Todo(models.Model):
HIGH = 3
MEDIUM = 2
LOW = 1
CHOICES_PRIORITY =(
(HIGH, _(‘High’)),
(MEDIUM, _(‘Medium’)),
(LOW, _(‘Low’))
)
COMPLETED = 1
TBD =2
CHOICES_STATUS=(
(COMPLETED, _(‘Completed’)),
(TBD, _(‘To be Done’))
)
A continuacion escribimos los campos que tendra nuestro modelo, django nos provee unos tipos basicos de fields, entre ellos tenemos el foreignkey que nos permitira relacionar nuestra entidad debil con una fuerte. En nuestro caso un User sera dueño de uno o mas todos.
owner = models.ForeignKey(User, related_name=’owner_group’, verbose_name=_(‘owner’))
# el atributo related se usa para indentificar desde el Usr al conjunto de “todos” que le pertenecen, mientras que el verbose name es la cadena que se usara para representar a ese campo.
name = models.CharField(_(‘name’), max_length=32)
# el tipo Charfield tiene como atributo obligatorio definir un maximo de letras de contenido, que sera un entero mayor a 1
created_date=models.DateTimeField(default=datetime.now)
# el atributo default lo usamos para definir valores por defecto, el valor por defecto sera la fecha de hoy, now la pasamos como callbak (se ejecutara la funcion now cada vez que se la requiera)
priority = models.IntegerField(_(‘priority’), choices=CHOICES_PRIORITY)
status = models.IntegerField(_(’status’), choices=CHOICES_STATUS)
# El atributo choices nos permite pasarle una lista de valores validos para dicho campo
description = models.TextField(_(‘description’))
due_date = models.DateField(_(‘due_date’),blank=True,null=True,)
completed_date = models.DateField(_(‘completed_date’),blank=True,null=True)
class Meta:
ordering = (‘created_date’,'priority’)
verbose_name = _(‘Todo’)
verbose_name_plural = _(‘Todo List’)
unique_together = (“owner”, “name”)
get_latest_by = ‘created_date’
order_with_respect_to=’owner’
# Estas son algunas de las opciones que tenemos para definir los metadatos de nuestro modelo, estos se definen definiendo la clase interna Meta. (En otro post veremos con mas detalle las difrentes opciones, aunque muchas de elas son faciles de predecir)
def __unicode__(self):
return self.name
# el unicode django automaticamente nos proveera el metodo __str__() que llamara a nuestro metodo _unicode__ y entonces convertira el resultado del mismo a una codificaciion de cadena de objetos UTF-8 correctamente. Para versiones mayores de django 1.0 es aconsejable usar unicode y no asi str.
Para que nuestro modelo pueda ser tomado en cuenta por el admin de django debemos registrarlo, para ello dentro de nuestra aplicacion creamos el archivo admin.py y lo minimo requerido para registrarlo seria tener lo siguiente:
(archivo: admin.py)
from django.contrib import admin
from models import Todo
admin.site.register(Todo) # aca registramos nuestro modelo con el admin de django
Ahora nos toca generar la base de datos:
./admin.py syncdb
Simepre la primera vez que sincronizamos nos pedira registremos las credenciales de nuestro usuario administrador (dile yes
).
Para habilitar completamente las interfaz administrativa debemos editar el urls.py de nuestro proyecto y tener algo como sigue:
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns(”,
(r’^admin/(.*)’, admin.site.root),
)
Ahora podemos hacer correr nuestro proyecto con:
#./manage.py runserver 0.0.0.0:8000
Ahora nos vamos al browser y colocamos:
Usando las credenciales que registramos al realizar el sync de bd ingresamos al sitio de administracion de djano.
Sin duda esta caracteristica de django es la que atrae a muchos, ya que en la mayoria de las aplicaciones que realizamos siempre necesitamos tener esta interfaz administrativa, aunque existen muchas cosas que se estan mejorando aun, no cabe duda que el admin de django nos ahorrara mucho trabajo.
