El ORM junto a los formularios, según mi opinión, son las partes más potentes y destacables que tiene Django. Ambos componentes hacen que trabajar con este framework sea más liviano. Pero dicho esto, obviamente, no quiere decir que estén completos o que no contengan errores. En este artículo voy a proponer dos nuevos lookups, para completar el ORM.

Hace un par de meses leí una pregunta en stackoverflow, en ella se preguntaba como se podía realizar una consulta SQL muy sencilla con el ORM de Django, una consulta como la siguiente:

SELECT * FROM auth_user WHERE username LIKE '10%8%0%'

Al principio pensé que solo estaba preguntando por una consulta utilizando el lookup contains, pero no era así. En Django no hay ninguna manera de conseguir esto. Solo se puede conseguir el mismo resultado, emulando la consulta con expresiones regulares:

User.objects.filter(username__regex=r'^10.*8.*0.*$')

Con lo que entendí que eran necesarios dos nuevos lookups: like y ilke. Cree un parche, y mientras lo aceptaban realicé un modulo django-like, para que la comunidad pudiera probarlo fácilmente. El cual, mediante monkey-patching, hace lo mismo que el parche. Con lo que la anterior consulta se quedaría en esta otra:

User.objects.filter(username__like='10%8%0%')

Motivos a favor

Los motivos por los que creo que debería de añadirse al core de Django son los siguientes:

Legibilidad

La consulta con like es bastante más corta y sencilla que con regex.

Rendimiento

Creo que este punto no es el más importante; en caso de que no hubiera habido mejora, aún así vería bien que se incluyeran dichos lookups, ya que se ganaría en legibilidad.

Muestro una tabla con la mejora que se obtiene tras ejecutar el comando benchmark_like, el cual compara el tiempo de ejecutar 10.000 consultas equivalentes haciéndolas con like y con regex.

postgres mysql sqllite oracle
like 0:00:50.727005 0:00:14.025656 0:01:36.089407 ?:??:??.??????
regex 0:01:38.410019 0:02:57.255685 0:09:39.527765 ?:??:??.??????
 mejora  254%  600%  503%  ???%

Funcionalidad Incompleta

Los backends que soporta Django, por defecto, son postgres, mysql, sqlite y oracle. En todos ellos existe la posibilidad de realizar una consulta a la base de datos con LIKE, por tanto debería de existir un lookup con el que se pudiera realizar esto.

Motivos en contra

Este parche no ha sido aceptado, me han dado una serie de motivos los cuales, exceptuando el primero, no comparto.

El nombre no es genérico

Es cierto que el nombre no es genérico, que tiene mucho que ver con la sintaxis SQL. Pero no lo veo un motivo para rechazarlo, lo veo un motivo para buscar un nombre mejor. Este podría ser: econtains la e sería de escape.

Rendimiento

Otro motivo que me han dado es el del rendimiento. Tras indicar que con LIKE las consultas son mucho más eficientes que con REGEX, me indicaron que esto no ocurría en postgres. Lo cual me asombró, y por este motivo cree el benchmark. Como se puede apreciar en la tabla anterior, en postgres no hay tanta diferencia, como en mysql o sqllite pero la mejora es indudable.

Duplicidad de código

Otro de los motivos dados, es que si ya se puede hacer con regex, por que hacerlo de otra manera. Yo estoy totalmente en contra de la duplicidad de código, soy a veces demasiado estricto en este tema, se puede ver un ticket en Django que cree. Pero este caso no es duplicidad de código ni de funcionalidad, y como dije las personas que piensen esto les animo a no utilizar contains, startswith, endwith, etc y hacer todas las consultas con regex, las cuales se pueden, pero se perdería en legibilidad y eficiencia.

Related Posts:

Etiquetado con:          
 

  1. P. van Kampen dice:

    Would this not work?

    User.objects.extra(where=["username like='10%%8%%0%%'"])

    (You have to escape the % but otherwise it is pretty much the SQL you want executed. )

  2. Pablo Martín dice:

    This would be without the “=” symbol. But this was only a example. Imagine something like this:

    User.objects.filter(Q(groups__name__ilike='john %') |
                        Q(username__ilike='john%'))
    

    Maybe it is possible to do with extra/where. Even you can to do it without ORM. But I don’t think that was more readable

    Thanks

  3. Web Center Design.com - Campinas | Criacao de Sites | WebDesign | Publicidade | Propaganda | Marketing | Otimizacao de Sites | Logica Digital | Cartao de visita | Panfletos | Folders | Impressos | Grafica dice:

    I’ll immediately take hold of your rss as I can not find your e-mail subscription hyperlink or newsletter service. Do you have any? Kindly allow me recognise in order that I may just subscribe. Thanks.

  4. publicidade dice:

    Wow, marvelous weblog format! How lengthy have you ever been running a blog for? you made blogging glance easy. The full look of your site is great, let alone the content material!

  5. design dice:

    Great beat ! I wish to apprentice whilst you amend your web site, how can i subscribe for a blog website? The account aided me a acceptable deal. I were a little bit acquainted of this your broadcast offered brilliant clear concept

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>