es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Ordenando campos personalizados en el administrador de Django.

Tengo un modelo de User con los siguientes campos:
“`python

<h1>models.py</h1>

class User(models.Model):

first<em>name = models.CharField(max</em>length=255)
middle<em>name = models.CharField(max</em>length=255, null=True, blank=True, default="")
last<em>name = models.CharField(max</em>length=255)

“`

He escrito un campo personalizado como se muestra a continuación que se puede ordenar por first_name, middle_name y last_name:
“`python

@admin.register(User)
class UserAdmin(BaseUserAdmin):
list<em>display = ("username", "email", "full</em>name", "is<em>staff", "date</em>joined")
list<em>filter = ("is</em>staff", "is_active")

<pre><code>@admin.display(ordering=("first_name", "middle_name", "last_name"))
def full_name(self, user: User):
return f"{user.first_name} {user.middle_name} {user.last_name}"
</code></pre>

“`

Pero admin.display(ordering=...) no funciona con múltiples campos como se menciona anteriormente.

¿Cómo puedo hacer que este campo personalizado sea ordenado por múltiples campos?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Desafortunadamente, admin.display(ordering=...) no admite la ordenación por varios campos. Sin embargo, puedes lograr esto creando un método personalizado de queryset utilizando annotate() y order_by().

    Aquí tienes un ejemplo:

    from django.db.models import CharField, Value
    
    # ...
    
    class UserQuerySet(models.QuerySet):
    
        def full_name(self):
            return self.annotate(
                fullname=CharField(
                    Value('') + 'first_name' + Value(' ') + 'middle_name' + Value(' ') + 'last_name',
                    output_field=models.CharField()
                )
            ).order_by('first_name', 'middle_name', 'last_name')
    
    @admin.register(User)
    class UserAdmin(BaseUserAdmin):
        list_display = ("username", "email", "full_name", "is_staff", "date_joined")
        list_filter = ("is_staff", "is_active")
    
        def get_queryset(self, request):
            return UserQuerySet(self.model, using=self._db)
    
        def full_name(self, user: User):
            return user.fullname
    
        full_name.admin_order_field = 'fullname'
    

    Aquí, definimos un método de queryset personalizado full_name() que crea un nuevo campo fullname utilizando annotate(). Concatenamos los campos first_name, middle_name y last_name en un solo CharField utilizando Value() y output_field=models.CharField().

    Luego ordenamos el queryset por los campos first_name, middle_name y last_name utilizando order_by().

    En la clase UserAdmin, anulamos el método get_queryset() para utilizar nuestro queryset personalizado. También definimos el método full_name() para devolver el campo fullname y establecemos su admin_order_field en 'fullname'.

    Con estos cambios, ahora podemos ordenar por el campo personalizado full_name con varios campos en la administración de Django.

Comments are closed.