Campos calculados en django
Las operaciones sobre los objetos model de django se mapean a SQL mediante el ORM (Object-relational mapping). Un problema que tiene el ORM de django es que no tiene soporte directo para los campos calculados, que son aquellos que se obtienen a partir de los valores de los campos del registro para cada registro.
Por ejemplo, tenemos unos movimientos en los que interviene cantidad, precio y comisión. ¿Qué sentido tiene guardar en la BD el campo importe si en realidad ya tenemos toda la información para calcularlo?.
class Movimiento(models.Model):
cantidad=models.DecimalField()
precio=models.DecimalField()
comision=models.DecimalField()
¿Cómo calculamos entonces el importe?. Hay dos alternativas: Una usando una property de python en el propio objeto model y otra usando extra en el queryset. Veamos:
class Movimiento(models.Model):
cantidad=models.DecimalField()
precio=models.DecimalField()
comision=models.DecimalField()
def _get_importe(self):
return self.cantidad*self.cambio*(1-self.comision)
importe = property(_get_importe)
Y ahí tenemos el importe del movimiento via movimiento.importeLa otra solución es usar extra en el queryset para añadir "a mano" el campo en la consulta SQL, sería:
target=movimiento.objects.extra(select={
'importe': 'cantidad*cambio*(1-comision)',})
for f in target:
print f.importe
Entonces, ¿Cuál es el problema?. Pues que todo esto son soluciones "de mentirijilla" puesto que realmente el campo importe no existe como tal en el gestor de BD y no podemos hacer cosas como sumar todos los importes haciendo una agregación, así esto
total_importe=modelo.aggregate(Sum('importe'))
Nos genera un error diciendo que el campo importe no existe.
Sin duda, el soporte para campos calculados es uno de las mejoras del ORM que puede trabajarse.
Fuentes:
http://stackoverflow.com/questions/3690343/django-orm-equivalent-for-this-sql-calculated-field-derived-from-related-table
Localizar las plantillas
Si queremos que los importes monetarios de nuestras plantillas nos salgan (en España) así: 1.256,56 €
en vez de así:1256.56 €
tenemos que localizar la plantilla y dejar que django haga el trabajo duro.
Para empezar, en settings.py indicamos que queremos usar la localización añadiendo:DEFAULT_CHARSET='utf-8'
THOUSAND_SEPARATOR= '.'
DECIMAL_SEPARATOR = ','
NUMBER_GROUPING = 3
USE_THOUSAND_SEPARATOR = True
FIRST_DAY_OF_WEEK = 1
LANGUAGE_CODE = 'es-es'
USE_L10N = True
En la plantilla, cargamos l10n y activamos la localización así:{% load l10n %}
{% localize on %}
blah, blah, blah...
{% endlocalize %}
Y de forma mágica los importes aparecerán correctamente formateados. Para controlar la cantidad de decimales diferentes del estándar también podemos usar el filtro floatformat:precision así:{{ importe|floatformat:6 }}
Error de codificación de caracteres al generar pdf con django y pisa
Hacía tiempo que me perseguía un pequeño problema al generar pdf desde django/pisa con caracteres utf8>255. Por defecto, pisa usa latin-1/ISO 8859-1 (un byte) para generar los pdf y al transcodificar los caracteres de la template (p.e. el símbolo euro €) me saltaban errores.
En la doc oficial de pisa tenemos que:pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), result)
Pero buscando en stackoverflow he encontrado que pisaDocument acepta además el parámetro encoding con el que en realidad le indicamos la codificación que debe usar con lo que queda:pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), result, encoding='UTF-8')
;-)
Minimizar y maximizar en gnome3
Una forma de configurar los botones que queremos en el marco de la ventana es instalar el programasudo apt-get install gnome-tweak-tool
Y desde él configurar este y otros aspectos del entorno.