2012-04-19 3 views
5

Estoy tratando de ordenar una página de la lista de administración de Django por un valor específico en el conjunto de claves externas relacionadas con los objetos.Administrador de Django: Ordenar por valor en la clave externa relacionada

Específicamente, en el código siguiente, deseo que la vista ContentAdmin muestre una lista de todos los objetos de contenido ordenados por el "Puntaje de Twitter" (El objeto de puntaje con el nombre "Twitter").

En la aplicación Django tengo los siguientes modelos:

class Content(models.Model): 
    body = models.CharField(max_length=564) 
    title = models.CharField(max_length=64) 

class Score(models.Model): 
    name = models.CharField(max_length=64) 
    score = models.IntegerField() 
    content = models.ForeignKey('Content') 

Y en el admin.py Tengo el siguiente:

class ContentAdmin(admin.ModelAdmin): 
    list_display = ('title', 'show_twitter_score',) 

    def show_twitter_score(self, obj): 
     twitter_score = obj.score_set.get(name='Twitter') 
     return 'Twitter: ' + str(twitter_score.score) 

OBJETIVO: El panel de administración para ContentAdmin muestra los objetos de contenido ordenado por "Twitter" puntuaciones

¡Gracias a todos!

+0

¿Cuál es incorrecto con su código? –

+0

¿Por panel de administración quieres decir 'admin.py'? ¿Tiene un 'admin.site.register (Content, ContentAdmin)'? –

+0

Mi código no hace el pedido, solo muestra los puntajes – djs22

Respuesta

4

Resolví esto extendiendo el método get_queryset de la clase ContentAdmin. Después de eso, era sólo una cuestión de conseguir el ORM consulta derecha

def get_queryset(self, request): 
    qs = super(ContentAdmin, self).get_queryset(request) 
    return qs.filter(score__name='Twitter').order_by('-score__score') 

Para Django 1.5 y anteriores, el método era queryset.

def queryset(self, request): 
    qs = super(ContentAdmin, self).queryset(request) 
    return qs.filter(score__name='Twitter').order_by('-score__score') 
0

Si he entendido bien, puede intentar esto desde ModelAdmin.list_display en la documentación de Django:

Por lo general, los elementos de list_display que no son campos de bases de datos reales no se pueden utilizar en la clasificación (porque Django hace todo el clasificación en el nivel de la base de datos).

Sin embargo, si un elemento de list_display representa un campo de base de datos determinado, puede indicar este hecho configurando el atributo admin_order_field del elemento.

Por ejemplo:

class Person(models.Model): 
    first_name = models.CharField(max_length=50) 
    color_code = models.CharField(max_length=6) 

    def colored_first_name(self): 
     return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name) 
    colored_first_name.allow_tags = True 
    colored_first_name.admin_order_field = 'first_name' 

class PersonAdmin(admin.ModelAdmin): 
    list_display = ('first_name', 'colored_first_name') 

Lo anterior le dirá a Django a la orden por el campo nombre apellido cuando se trata de ordenar por colored_first_name en el admin.

Puede probar esta solución en su código para la ordenación.

+0

Gracias Cesar, pero no creo que esto funcione para mí. Usando list_display no tengo forma de especificar cuál de las puntuaciones múltiples en el content_obj.score_set quiero ordenar. Además, ¿puedo aclarar mi pregunta por usted? Quiero asegurarme de que sea entendible por todos – djs22

+0

Claro, simplemente re-edite su publicación y cambie lo que necesita. Lo siento, tal vez no entendí todo el asunto, no sería la primera vez :( –

+0

Hice una pequeña edición en la parte inferior de GOAL, pero desafortunadamente no sé cómo más para formular la pregunta. ¡Gracias por intentarlo, César! – djs22

0

Dado que django admin usa la base de datos para ordenar, no se puede ordenar la función que se muestra en la lista.

Lo que puede hacer es agregar la columna que desea mostrar al conjunto de consulta que utiliza django admin para listar sus modelos, de esta manera puede tener la clasificación.

Para agregar la columna que necesita, debe usar el método adicional queryset.

Esto debería hacer el truco :)

Content.objects.all().extra(select={'twitter_score': 'SELECT score from content_score WHERE content_score.id = content_content.id'}) 

ronda de bonificación:

Content.objects.all() extra (seleccione = { 'twitter_score': 'SELECT 'puntuación de Twitter:'. | puntaje de content_score WHERE content_score.id = content_content.id '})

+0

Definitivamente es posible hacer esto dentro de los reinos del ORM. Encontré una solución para esto que publicaré en breve, comentaré aquí cuando tenga :) – djs22

+0

En realidad, pasará un tiempo hasta que responda, ¡No puedo hacerlo por otras 8 horas! – djs22

+0

@ djs22 tengo curiosidad por ver este :) –

Cuestiones relacionadas