¿Qué es CodenerixModel?
🇬🇧 Read it in English, “CodenerixModel“ En el artículo anterior hablábamos sobre CODENERIX y sus bondades. Ahora vamos a comenzar una serie de artículos que permitan...
Filter by Category
Filter by Author
🇬🇧 Read it in English, “CodenerixModel“ En el artículo anterior hablábamos sobre CODENERIX y sus bondades. Ahora vamos a comenzar una serie de artículos que permitan...
Posted by Juanmi Taboada
Tal y como Google anunciaba en su blog oficial, aquellos usuarios que accedan al calendario desde la web comenzarán a ver un nuevo diseño mucho más limpio basado en el estándar de...
Posted by Juanmi Taboada
Poodle se convierte en una amenaza para la red, se recomienda desactivar SSL3 del navegador. Hace tan sólo 2 días Google reveló una nueva vulnerabilidad que afecta a la...
Posted by Juanmi Taboada
¡¡¡ATENCIÓN: ESTE ES UN COMUNICADO DE VITAL IMPORTANCIA PARA SU EMPRESA!!! Desde finales de la semana pasada se habla en las noticias del Ransomware Wannacry y esta...
Posted by Juanmi Taboada
Open South Code – 5 y 6 Mayo (La Térmica, Málaga) EVENTO GRATUITO DE SOFWARE LIBRE CREATIVIDAD, TENDENCIAS EN PROGRAMACIÓN, FUTURO Tiene lugar la 2ª edición del...
Posted by Juanmi Taboada
🇬🇧 Read it in English, “What is it CODENERIX?“ Es el nombre que recibe el software libre generado por Centrologic para desarrollo de herramientas de gestión...
Posted by Juanmi Taboada
En este artículo hablamos del ciclo de vida de un dominio. El nombre de dominio está registrado o renovado. Los nombres de dominio pueden estar registrados o...
Posted by Juanmi Taboada
En primer lugar debemos conocer que para que exista el fichero .ibd debemos tener activado el sistema de almacenamiento Barracuda mediante la separación de ficheros por cada tabla...
Posted by Juanmi Taboada
Cada año durante las vacaciones, como buen informático, aprovecho para leer cosas diferentes y aprender algo nuevo, en esta ocasión he podido estudiar sobre la librería...
Posted by Juanmi Taboada
Ha llovido mucho desde que escribía (en Marzo de 2005) en mi antigua página Fibranet.org (ahora fuera de línea y totalmente redirigida a esta) y es que hoy por hoy lleva...
Posted by Juanmi Taboada
🇬🇧 Read it in English, “CodenerixModel“
En el artículo anterior hablábamos sobre CODENERIX y sus bondades. Ahora vamos a comenzar una serie de artículos que permitan profundizar en esta tecnología.
Para que todo proyecto Django pueda soportar CODENERIX adecuadamente es necesario dar algunos pasos importantes que aseguren el buen comienzo del proyecto. No voy a repetir que la forma más sencilla de comenzar es usando los Ejemplos de CODENERIX disponibles en GITHUB.
Es por ello que en esta ocasión me voy a centrar en el CORE / KERNEL de CODENERIX y que conoceremos de ahora en adelante como CodenerixModel.
CodenerixModel no es más que la extensión del sistemas models.Model de Django donde se contemplan una serie nueva funcionalidades que explicaré a continuación. En primer lugar debemos tener en cuenta que la mayoría de funcionalidades que veremos de CODENERIX se consiguen mediante el uso de herencia directa de clases de este framework. Para ello vamos a ver un sencillo de ejemplo de una clase desarrollada con CODENERIX:
from codenerix.models import CodenerixModel from django.db import models class Author(CodenerixModel): name = models.CharField(_(u'Name'), max_length=128, blank=False, null=False) birth_date = models.CharField(_(u'Fecha de nacimiento'), max_length=128, blank=False, null=False) def __fields__(self, info): fields=[] fields.append(('name', _('Name'), 100, 'left')) fields.append(('birth_date', _('Birth Date'))) return fields
En este ejemplo vemos varias cosas que nos llaman la atención frente a una declaración normal de un modelo en Django:
from codenerix.models import CodenerixModel
class Author(CodenerixModel):
def __fields__(self, info):
debemos saber que este método debe estar definido en todas las clases que hereden de CodenerixModel dado que es usada por CODENERIX para conocer como debe mostrar la información al usuario final de la aplicación de tal modo que esta sea clara, sencilla y usable.
Recoge qué información del modelo es útil ser mostrada cuando el usuario desee trabajar con dicho modelo. Este método es llamado normalmente por los listados, dado que los campos que aparecen aquí serán usados como columnas en el listado.
def __fields__(self, info): fields=[] fields.append(('name', _('Name'), 100, 'left')) fields.append(('birth_date', _('Birth Date'))) return fields
IMPORTANTE: Este método es obligatorio en todos los modelos que hereden de CodenerixModel.
El método recibe un argumento “info” que contiene información sobre la consulta recibida (request) incluyendo entre otros datos el usuario que la hace y otra meta información importante para la toma de decisiones que se hará dentro de __fields__. Este ejemplo es lineal, pero podemos aprovechar esta información para detectar el nivel de acceso de un usuario y mostrar unos campos u otros en el listado, adaptando el contenido del listado en función del usuario o las condiciones del sistema.
De este método se espera que responda con una lista de tuplas que debe contener al menos 2 elementos, el primero será el nombre del campo según el modelo de Django y el segundo el nombre traducible de dicho campo para ser mostrado al usuario en el título de la columna a la que hace referencia ese campo.
Cada tupla por lo tanto se compone de 2 elementos obligatorios y varios opcionales que paso a enumerar:
Existen otros 3 métodos especiales más que aportan diferentes funcionalidades a los modelos, estos son: __limitQ__, __searchF__ y __searchQ__.
Es un método limitante, su objetivo consiste en limitar los resultados a los que el usuario tiene acceso. De este modo limitQ permite controlar el resultado devuelto al usuario en función al entorno de consulta, de tal modo que si eres un usuario sin privilegios, no podrás ver ciertos registros porque se aplicará un filtro. Es muy útil cuando se trabaja con Roles dado que permite controlar los registros que ve el usuario en función al rol que tiene.
def __limitQ__(self, info): limits = {} if not info.user.is_admin: criteria = [] criteria.append(Q(model__pk=pk_condition)) criteria.append(Q(model__field1=condition)) limits['profile_people_limit'] = reduce(operator.or_, criterials) return limits
El método espera devolver un diccionario donde la key indica simplemente la línea que opera (por si ocurre un error al procesar la búsqueda) y por otro lado el valor es un objeto Q de Django. El objeto Q será inyectado en el Queryset del listado cuando este sea solicitado aplicándose o no el filtro en función a la consulta.
Es el método utilizado para filtrar las consultas con el texto que se introduce en la caja superior de los listados. De este modo todo aquello que el usuario escriba en la caja de búsqueda nos llegará en la variable “text” y esto permitirá filtrar la búsqueda con este texto.
def __searchQ__(self, info, text): text_filters = {} text_filters['identifier1'] = Q(CharField1__icontains=text) text_filters['identifier2'] = Q(TextField1__icontains=text) text_filters['identifier3'] = Q(IntegerField=34) #If text have this a especific word can return another Q condition. if text.find(u'magic') != -1: text_filters['identifier4'] = Q(identifier=34) return text_filters
El método espera devolver un diccionario donde la key indica simplemente la línea que opera (por si ocurre un error al procesar la búsqueda) y por otro lado el valor es un objeto Q de Django. El objeto Q será inyectado en el Queryset del listado cuando este sea solicitado aplicándose o no el filtro en función a la consulta.
Es el encargado de mostrar los filtros de búsqueda y es usado cuando deseamos que se muestren filtros que faciliten la búsqueda. En concreto su uso se refiere a la definición personalizada de estos filtros, por ejemplo un selector que muestre “A”, “M” y “S”, de tal modo que si pulsas “A” buscarás todo lo que empiece por “A”, idem para M y S, pero no podrás hacer búsqueda por otras letras. Es muy útil para construir búsqueda combinadas, por ejemplo: “dame los del tipo A” (que se refieren a los verdes y morados conjuntamente). También es usado para generar filtros complejos. CODENERIX incluye de forma automática filtros en todos los campos de un listado con los que sabe operar de forma nativa, así por ello saldrán filtros para los campos de texto, campos numéricos, BooleanFields, ChoiceFields y fechas.
def __searchF__(self, info): list1 = [] for l1 in Model.objects.all(): list1.append((l1.id, l1.field1 + ' ' + l1.field2)) list2 = [] for li in Model2.objects.all(): list2.append((li.id, str(li.field))) text_filters = {} text_filters['field1'] = (_('Field1'), lambda x: Q(field1__startswith=x), [('h', _('Empieza con h')), ('S', _('Empieza con S'))]) text_filters['field2'] = (_('Field2'), lambda x: Q(field2__pk=x), list1) text_filters['external'] = (_('Field3'), lambda x: Q(pk=x),list2) return text_filters
El método espera devolver un diccionario donde la clave del diccionario indica el nombre del filtro, si el nombre del filtro coincide con un campo del listado, entonces el filtro se mostrará en la fila oculta debajo del título del listado y que se despliega con el icono “≡”, en caso contrario se mostrará como un filtro externo. El valor de dicha clave deberá ser una tupla con 3 elementos:
(_('Field1'), lambda x: Q(field1__startswith=x), [('h', _('Empieza con h')), ('S', _('Empieza con S'))])
de tal modo que el primer elemento será el nombre del filtro en formato traducible, el segundo una función lambda que recibe el valor del filtro y devuelve un objeto Q que ayuda a que ese filtro funcione del modo en que se espera, el tercer elemento deberá ser una lista con las opciones que se van a mostrar en el filtro. El objeto Q devuelto por la función lambda será inyectado en el Queryset del listado cuando este sea solicitado aplicándose o no el filtro en función a la consulta.
Aunque más adelante hablaremos de GenList (vista usada para construir los listados) debo decir que __fields__, __limitQ__, __searchQ__ y __searchF__ son métodos que pueden aparecer indistintamente en el modelo y en la vista de un listado. A continuación se muestra cómo interaccionan los filtros cuando un modelo especifica un filtro y un listado no, o viceversa.
En las siguientes 3 tablas se muestran 3 columnas:
__fields__ |
||
CodenerixModel | GenList | Se aplica… |
NO | NO | — ERROR — |
NO | SI | — ERROR — |
SI | NO | CodenerixModel |
SI | SI | GenList |
__limitQ__ |
||
CodenerixModel | GenList | Se aplica… |
NO | NO | No se aplica ningún filtro |
NO | SI | Se aplica filtro de GenList |
SI | NO | Se aplica filtro de CodenerixModel |
SI | SI | Se aplica filtro de GenList y de CodenerixModel uniendo a ambos mediante el operador lógico “AND“. |
__searchQ__ & __searchF__ |
||
CodenerixModel | GenList | Se aplica… |
NO | NO | No se aplica ningún filtro |
NO | SI | Se aplica filtro de GenList |
SI | NO | Se aplica filtro de CodenerixModel |
SI | SI | Se aplica filtro de GenList |
Estas tablas las recordaremos de nuevo más adelante cuando explique GenList al detalle.
Además de los métodos anteriores debemos destacar que CodenerixModel añade una serie de funcionalidades extras a los modelos estándares de Django.
def lock_delete(self): if self.documents.exists(): return _("No se puede borrar el apunte, existe un documento que lo bloquea") elif self.people.exists(): return _("No se puede borrar el apunte, existen personas aun trabajando con él") else: return super(Apunte, self).lock_delete()
En este ejemplo se impide el borrado de un apunte cuando tiene documentos asociados o cuando hay personas usándolo, en otro caso se delega la responsabilidad a la clase padre.
Ahora ya estamos preparados para aprender el uso de GenList.
Yes, I am a developer who writes its stuff with “vim”. What’s up? Several times I have discussed if Vim is or is not an IDE. Many people don’t understand...
It happened some time (years) while I was thinking about the problem of programming languages nowadays. I mean, I was asking questions myself like: – Is there some program...