2012-09-10 8 views
46

Una de mis modelos tiene una bandera borrado, que se utiliza para ocultar objetos a nivel mundial:Anulación queryset defecto en Django administrador

class NondeletedManager(models.Manager): 
    """Returns only objects which haven't been deleted""" 

    def get_query_set(self): 
     return super(NondeletedManager, self).get_query_set().exclude(deleted=True) 

class Conversation(BaseModel): 
    ... 
    deleted = models.BooleanField(default=False) 
    objects = NondeletedManager() 
    all_conversations = models.Manager() # includes deleted conversations 

¿Cómo puedo anular el conjunto de consultas por defecto utilizado por el módulo de administración de Django para incluir conversaciones eliminados?

+0

¿Realmente necesita administradores personalizados para esas consultas simples? –

+2

Sí, los objetos eliminados se deben ignorar universalmente (excepto en las páginas de administración), por lo que tiene sentido establecer un valor predeterminado. –

Respuesta

86

Puede overrideget_queryset método en su modelo de clase de administrador.

class MyModelAdmin(admin.ModelAdmin): 
    def get_queryset(self, request): 
     qs = super(MyModelAdmin, self).get_queryset(request) 
     if request.user.is_superuser: 
      return qs 
     return qs.filter(author=request.user) 

Nota de Django < = 1.5 el método fue nombrada simplemente queryset.

+2

¿Cómo funcionaría eso en este caso? ¿Puedo modificar el queryset creado por 'ModelAdmin.queryset' para incluir objetos eliminados? No quiero construir el queryset en lugar de invocar la superclase. –

+0

Mira mi respuesta para ver a qué me refiero. ¿Hay alguna alternativa a la reimplementación completa de la función? –

+3

Ayuda poner realmente la respuesta en su respuesta, en lugar de simplemente vincularla. Ese enlace está muerto ahora, entonces lo actualizaré para dar una explicación. – Dan

2

Lo que sería tan malo en lo siguiente:

class Conversation(BaseModel): 
    ... 
    deleted = models.BooleanField(default=False) 
    objects = models.Manager() # includes deleted conversations 
    nondeleted_conversations = NondeletedManager() 

Así que en sus propias aplicaciones/proyectos, se utiliza Conversation.nondeleted_conversations() y dejar que la incorporada en aplicación de administración haga su cosa.

+1

Estoy ignorando los objetos eliminados en todas partes * pero * las páginas de administración, por lo que creo que debería ser el valor predeterminado. Además, de esta forma no necesito actualizar el código heredado al agregar la capacidad de eliminar conversaciones. –

7

Konrad es correcto, pero esto es más difícil que el ejemplo dado en la documentación.

Las conversaciones eliminadas no pueden incluirse en un conjunto de consulta que ya las excluye. Por lo tanto, no veo otra opción más que volver a implementar admin.ModelAdmin.queryset por completo.

class ConversationAdmin (admin.ModelAdmin): 

    def queryset (self, request): 
     qs = Conversation.all_conversations 
     ordering = self.get_ordering(request) 
     if ordering: 
      qs = qs.order_by(*ordering) 
     return qs 
+0

No creo que haya nada de malo en eso. Usar dos gerentes es el camino a seguir. Sin embargo, es cierto que el administrador de Django podría proporcionar un gancho para que no tenga que volver a implementar la parte de pedido. –

1

La solución aceptada funciona muy bien para mí, pero yo necesitaba un poco más de flexibilidad, por lo que terminó la ampliación de la vista de lista de cambios para agregar en un parámetro queryset personalizado. Ahora puedo configurar mi queryset/filter predeterminado como tal y aún se puede modificar utilizando un filtro diferente (obtener parámetros):

def changelist_view(self, request, extra_context=None): 
    if len(request.GET) == 0 : 
     q = request.GET.copy() 
     q['status__gt'] = 4 
     request.GET = q 
     request.META['QUERY_STRING'] = request.GET.urlencode() 

    return super(WorksheetAdmin,self).changelist_view(request, extra_context=extra_context) 
Cuestiones relacionadas