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...
{{ comments.length }} comentarios