Lookup fields customitzats en Django
Published on junio 3rd, 2018
Django, de manera genèrica, ens proveeix una API del seu ORM a través de la qual ens permet executar els "querysets" que necessitem de manera més o menys optima. Malgrat això, es pot donar el cas que necessitem realitzar algun tipus de consulta una mica més customitzada o millorada. Per a tal efecte, disposem de tota una sèrie d'eines, ja siguin els objectes Q, les expressions F, els Field Lookups, etc. Sobre aquest darrer grup, els Field lookup's tenim la possibilitat de definir els nostres propis.
Per a implementar un "Lookup field" hem d'implementar una classe que ens permeti personalitzar
la part esquerra i la part dreta de la clàusula sql. Es fa estenent la classe Lookup
del paquet "django.db.models.fields.Lookup
" i, posteriorment, registrant aquest classe
personalitzada amb el mètode register_lookup
de la classe django.db.models.fields.Field
.
E.g.:
from django.db.models import Lookup
from django.db.models.fields import Field
class Lower(Lookup):
"""
Custom lookup for postgres "lower" function implementation
"""
lookup_name = 'lower'
def as_sql(self, qn, connection):
lhs, lhs_params = self.process_lhs(qn, connection)
rhs, rhs_params = self.process_rhs(qn, connection)
params = lhs_params + rhs_params
return 'lower({}) = {}'.format(lhs, rhs), params
Field.register_lookup(Lower)
L'exemple en concret implementa la funcionalitat de comparar el contingut d'un camp en minúscula amb la cadena que nosaltres li passem. Hi ha varis punts importants:
lookup_name = 'lower'
Defineix el nom que emprarem per executar la clàusula.
lhs, lhs_params = self.process_lhs(qn, connection)
Compila la part esquerra de la clàusula
rhs, rhs_params = self.process_rhs(qn, connection)
Compila la part dreta de la clàusula
Field.register_lookup(Lower)
Registrem el custom lookup per tal de poder-lo emprar.
Finalment, un exemple d'ús del nostre custom lookup seria:
try:
task = TransTask.objects.filter(object_class__lower=class_name).get()
except TransTask.DoesNotExist:
task = None
object_class__lower=class_name
és la part on s'aplica el "custom lookup". Compararà el contingut en minúscula del camp
object_class
amb el contingut de la variable class_name
.