[Django][DRF] ¿Cómo obtener un conjunto de consultas DESORDENADO a partir de `.filter`?
Antes que nada, no soy un hablante nativo de inglés, así que por favor ten paciencia con mis habilidades en inglés o dame algunos consejos.
(Para tu información, Django versión 3.2.9 y DRF versión 3.12.4 con PostgreSQL versión 12.7)
Estoy escribiendo una API para crear una publicación utilizando el serializador de DRF. Y me he enfrentado a un problema con “el orden en el que se agregan las etiquetas a la publicación”.
- Los modelos de publicación y etiquetas están conectados a través de un campo M2M.
Lo que significa que, digamos que añado las etiquetas a, b y c en una publicación. La lógica que estoy utilizando es la siguiente.
# Clase Serializador
# def create(instancia):
# instancia: instancia específica de la publicación
tags = ['t', 'a', 'g', 's']
Tag.objects.bulk_create([Tag(name=tag) for tag in tags])
instancia.tags.add(*[tag for tag in Tag.objects.filter(name__in=tags)])
Ejecuta esto al principio. Las etiquetas se agregan en este orden.
TagQuerySet[Tag<'t'>, Tag<'a'>, Tag<'g'>, Tag<'s'>]
Y mi API recibe otra solicitud de creación que incluye las etiquetas existentes, por ejemplo,
tags = ['g', 'a', 's']
Django las agrega en orden ascendente, no en el orden que quiero, como por ejemplo,
# Etiquetas de la nueva instancia creada
TagQuerySet[Tag<'a'>, Tag<'g'>, Tag<'s'>]
Sé que puedo agregar las etiquetas siguiendo mi orden de lista usando un bucle for,
for tag in tags:
instancia.tags.add(Tag.objects.get(name=tag))
pero no es eficiente.
Entonces mi pregunta es:
- ¿Cómo puedo obtener una consulta utilizando
.filter
siguiendo el orden de mi lista? - Si no hay forma de hacer esto, ¿cuál es la forma eficiente de agregar etiquetas a la publicación?
davy.ai
queryset
utilizando.filter
siguiendo el orden de mi listaDesafortunadamente,
.filter()
no admite la ordenación en el orden de la lista de entrada. Según la documentación de Django, el orden de los resultados al utilizar.filter()
es indefinido (https://docs.djangoproject.com/en/3.2/topics/db/queries/#retrieving-specific-objects-with-filters). Por lo tanto, no puedes confiar en el orden en el que los elementos de la lista son devueltos por el método.filter()
.Una forma eficiente de agregar etiquetas a una publicación es verificar primero si la etiqueta ya existe en la base de datos. Si la etiqueta ya existe, simplemente puedes usar
.add()
para agregar la etiqueta a la publicación. Si la etiqueta no existe, puedes crear una nueva etiqueta utilizando.create()
y luego usar.add()
para agregarla a la publicación. Aquí tienes un ejemplo de código:Este código primero obtiene las etiquetas de los datos de la publicación y luego las recorre en un bucle para verificar si existen en la base de datos. Si una etiqueta ya existe, la agrega a una lista de objetos de etiqueta (
tag_objs
). Si una etiqueta no existe, crea una nueva etiqueta y la agrega a la lista.Finalmente, el código crea una nueva publicación y agrega la lista de objetos de etiqueta a ella utilizando
.add()
. De esta manera, se conserva el orden de las etiquetas en la lista de entrada y las etiquetas se agregan eficientemente a la publicación.