Django ordenar ignorando los acentos | Programador Web Valencia

Django ordenar ignorando los acentos

1 minuto

Django con acento

En caso que intentes ordenar una consulta de la base de datos y no uses PosgreSQL como base de datos principal te vas a encontrar un pequeño problema: Cuando hay acentos no se ordena de una forma lógica. Si utilizas SQLite te lo habrás encontrado de frente. Por ejemplo, si yo tengo una tabla con nombres e intento ordenarlas con order_by pasaré de:

Zaragoza, Ávila, Murcia, Albacete...

al siguiente orden

Albacete, Murcia, Zaragoza, Ávila...

Las palabras con acento, con ñ u otros carácteres acabarán al final de la lista.

Para arreglarlo he creado la siguiente solución que debes copiarlo en el archivo donde necesites realizar el orden deseado.

import re
import functools


def order_ignore_accents(queryset, column):
    """Order Queryset ignoring accents"""

    def remove_accents(raw_text):
        """Removes common accent characters."""
        sustitutions = {
            "[àáâãäå]": "a",
            "[ÀÁÂÃÄÅ]": "A",
            "[èéêë]": "e",
            "[ÈÉÊË]": "E",
            "[ìíîï]": "i",
            "[ÌÍÎÏ]": "I",
            "[òóôõö]": "o",
            "[ÒÓÔÕÖ]": "O",
            "[ùúûü]": "u",
            "[ÙÚÛÜ]": "U",
            "[ýÿ]": "y",
            "[ÝŸ]": "Y",
            "[ß]": "ss",
            "[ñ]": "n",
            "[Ñ]": "N",
        }
        return functools.reduce(
            lambda text, key: re.sub(key, sustitutions[key], text),
            sustitutions.keys(),
            raw_text,
        )

    return sorted(queryset, key=lambda x: remove_accents(eval(f"x.{column}")))

Supongamos, por ejemplo, que necesitas ordenar unos pueblos o municipios. Lo que haría cualquier desarrollador es:

towns = Town.objects.all().order_by('name')

En su lugar, omitirás order_by y añadirás la consulta a la función order_ignore_accents. Y como segundo argumento la columna que quieres usar para ordenar. En este caso será name.

towns_order = order_ignore_accents(Town.objects.all(), 'name')

Se ordenará como esperamos.

Albacete, Ávila, Murcia, Zaragoza...

Esta obra está bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivadas 4.0 Internacional.

Atribución/Reconocimiento-NoComercial-SinDerivados 4.0 Internacional

¿Me ayudas?

Comprame un café
Pulsa sobre la imagen

No te sientas obligado a realizar una donación, pero cada aportación mantiene el sitio en activo logrando que continúe existiendo y sea accesible para otras personas. Además me motiva a crear nuevo contenido.

Comentarios

{{ comments.length }} comentarios

Nuevo comentario

Nueva replica  {{ formatEllipsisAuthor(replyComment.author) }}

Acepto la política de Protección de Datos.

Escribe el primer comentario

Tal vez también te interese...