Campo Blueprint.sort_order (orden manual de secciones)
Descripción
Blueprint.sort_order es un nuevo campo en el modelo Blueprint (v1.50.0) que almacena el orden manual de las secciones del Dashboard (Maps y Filas).
Permite que cada organización tenga un orden personalizado y persistente del listado de maps/rows, en lugar del anterior orden fijo alfabético.
Definición
# blueprints/models.py
class Blueprint(models.Model):
# ... campos existentes ...
# Orden manual de las secciones del Dashboard (drag&drop, por organización).
# NULL = sin ordenar todavía → va al final; el siguiente reorder lo fija.
sort_order = models.IntegerField(null=True, blank=True)
Características
| Aspecto | Valor |
|---|---|
| Tipo | IntegerField |
| Nullable | Sí (null=True, blank=True) |
| Default | None (NULL en BD) |
| Scope | Por organization (FK) |
| Índice | No (acceso por filtro + sort, no búsqueda high-volume) |
| Soft-delete | Respeta deleted_at (migración filtra activos) |
Semántica
sort_order = 0..N: posición explícita asignada por drag&drop (POST /api/blueprints/reorder).sort_order = NULL: blueprints sin ordenar aún (nuevos o nunca reordenados).- Aparecen al final en el listado.
- Entre ellos, se ordenan alfabéticamente por
name. - El primer reorder que los incluya les asigna índice definitivo.
- Orden final en vista:
(no_map, sin_ordenar, sort_order, nombre, rack).
Migración
Archivo: blueprints/migrations/0010_blueprint_sort_order.py (v1.50.0)
def backfill_sort_order(apps, schema_editor):
Blueprint = apps.get_model("blueprints", "Blueprint")
org_ids = Blueprint.objects.values_list("organization_id", flat=True).distinct()
for org_id in org_ids:
bps = list(Blueprint.objects
.filter(organization_id=org_id, deleted_at__isnull=True)
.order_by("name"))
for idx, bp in enumerate(bps):
bp.sort_order = idx
Blueprint.objects.bulk_update(bps, ["sort_order"])
Backfill:
- Por cada organización, ordena blueprints activos (no borrados) alfabéticamente por
name. - Asigna
sort_order = 0..N-1según ese orden. - Objetivo: deploy sin cambios visuales (preservar orden anterior).
Migración reversible: RunPython con noop (no deshacer el backfill, pero reverting el campo es seguro).
Caso de uso: Drag&Drop
# Frontend: usuario arrastra "Beta" al inicio
POST /api/blueprints/reorder
{
"blueprint_ids": [2, 1, 3] # Beta(2), Alpha(1), Gamma(3)
}
# Backend: asigna
Blueprint(id=2).sort_order = 0 # Beta → inicio
Blueprint(id=1).sort_order = 1 # Alpha
Blueprint(id=3).sort_order = 2 # Gamma
Siguiente render: racks_list() en core/htmx_views.py ordena por esta clave:
key=lambda r: (
r.blueprint_name == "", # "No Map" al final
r.blueprint_sort is None, # sin ordenar después
r.blueprint_sort, # orden manual
r.blueprint_name.lower(), # alfabético entre los sin ordenar
r.name.lower() # nombre del rack
)
Resultado: Beta → Alpha → Gamma en el Dashboard.
Acceso en vistas
Dos puntos de acceso aplican sort_order:
1. racks/views.py — First render (GET /)
def index(request):
# ... build racks_list ...
for rack in racks_list:
rack.blueprint_sort = first_placement.blueprint.sort_order if first_placement else None
racks = sorted(racks_list, key=lambda r: (
r.blueprint_name == "",
r.blueprint_sort is None,
r.blueprint_sort if r.blueprint_sort is not None else 0,
r.blueprint_name.lower(),
r.name.lower()
))
2. core/htmx_views.py — Refresh HTMX (partial)
def racks_list(request):
# ... build racks_list ...
for rack in racks_list:
rack.blueprint_sort = first_placement.blueprint.sort_order if first_placement else None
racks = sorted(racks_list, key=lambda r: (
r.blueprint_name == "",
r.blueprint_sort is None,
r.blueprint_sort if r.blueprint_sort is not None else 0,
r.blueprint_name.lower(),
r.name.lower()
))
Nota: ambas usan la misma clave de sort, requisito de {% regroup %} en template.
Performance
- Lectura:
sort_orderes un int → comparación rápida. - Escritura:
bulk_update()en una sola query por reorder (típicamente 3-20 blueprints). - Índice: no necesario (acceso siempre filtrado + sort, no búsqueda de igualdad).
Ejemplos de orden resultante
Organización Datacenter-A:
1. [sort_order=0] Maps → Alpha ← usuario lo arrastró primero
2. [sort_order=1] Maps → Gamma ← usuario lo arrastró segundo
3. [sort_order=NULL] Maps → Zeta ← nuevo, aún sin ordenar (alfabético)
4. [sort_order=2] Filas → Fila-1 ← usuario lo arrastró tercero
5. Rooms ← fijo
6. No Map ← fijo, siempre al final
Véase también
- [[feature—dashboard—reorder-sections-dragdrop]]
- [[entity—blueprints—endpoint—reorder]]
- [[entity—blueprints—model—blueprint]]
- [[entity—core—model—organization]]