Django


Soy un firme defensor del software libre desde hace años. Incluso estoy muy orgulloso de haber formado parte como becario de la Oficina de Software Libre de la Universidad de La Laguna. Desde que fundamos Galotecnia Redes Sistemas y Servicios hemos estado muy ocupados tratando de hacernos un hueco en el pequeño y competitivo mercado canario.

Como empresa trabajamos principalmente con Django, que en este tiempo ha crecido muchísimo. Trabajar con Django nos aporta muchas ventajas como por ejemplo no tener que compilar cada vez que queremos probar una modificación o poder trabajar con un lenguaje, Python, que posiblemente se acerque al equilibrio entre expresividad y rendimiento.

El hecho de que cada vez más y más gente esté trabajando con este framework hace que haya disponible cientos de líneas de código al alcance de la tecla. Esto es magnífico ya que te permite concentrarte en lo que hace distinta a tu aplicación.

Hace tiempo que no puedo picar código a gusto por distintos motivos, pero hoy he podido un poco. He estado trabajando en hacer cosas con la aplicación administrativa. La aplicación administrativa es bastante flexible y permite hacer cosas bastante chulas con bastante sencillez.

Controlar las entradas que se muestran a un usuario (código de django-blog-zinnia modificado) :

def queryset(self, request):
"""Make special filtering by user permissions"""
queryset = super(EntryAdmin, self).queryset(request)
if request.user.has_perm('zinnia.can_view_all'):
return queryset
return Entry.objects.filter(blog__in = request.user.blog_set.all())

El truco está en que el request tiene un atributo user, por lo que básicamente se pueden hacer muchas cosas muy interesantes.

Restringir las opciones de una ForeignKey:

def formfield_for_foreignkey(self, db_field, request, **kwargs):
if (request.user.is_superuser == False) and (db_field.name == "blog"):
kwargs["queryset"] = Blog.objects.filter(authors = request.user)
return db_field.formfield(**kwargs)
return super(EntryAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

Nuevamente tenemos el usuario en el request, en este caso es un poco más engorroso porque tenemos que filtrar por el nombre del campo, pero sigue siendo sencillo y potente.

Restringir las opciones de un ManyToMany:

def formfield_for_manytomany(self, db_field, request, **kwargs):
if (request.user.is_superuser == False) and (db_field.name == "related"):
kwargs["queryset"] = entries_published(Entry.objects.all(), request.user)
return db_field.formfield(**kwargs)
return super(EntryAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)

Es básicamente lo mismo que en el caso anterior. Ojo este método no está documentado, por lo que no estoy seguro de que sea buena idea utilizarlo.

Con estas tres opciones y alguna que otra que no he comentado podemos hacer que el contenido que cada usuario ve en la interfaz administrativa sea personalizado a dicho usuario lo cual es necesario en muchas ocasiones.

EDITADA: Corregida la indentación y el el return del ejemplo de manytomany

Anuncios

Sin duda alguna lo peor que tiene Django es que no garantiza la estabilidad de la API al menos hasta la versión 1.0. Esto hace que en muchos casos estes trabajando con varios proyectos que tienen diferentes versiones de Django. Mantenerlos todos en el trunk sería imposible, mientras que el trunk ofrece mejoras muy importantes con respecto a la versión estable, por lo que los proyectos nuevos suelen comenzarse con la versión en el repositorio en un momento dado.

Para gestionar esta diversidad una buena idea puede ser comprimir esa versión e introducirla dentro del sistema de control de versiones que se utilice en el proyecto. Lo suyo sería disponer de un lugar dentro del home (por ejemplo) con todas las versiones descomprimidas; y a la hora de comenzar a trabajar en un proyecto concreto exportar la variable PYTHONPATH de manera que se anteponga esa instalación de Django al resto de librerías.


$ export PYTHONPATH=/home/esauro/Django-0.95:$PYTHONPATH

Incluso cabría la posibilidad de incluir un fichero bash del que se haga source en cada proyecto, de manera que no tienes la necesidad de recordar con qué versión de Django se está trabajando en cada proyecto.