Uno de mis modelos tiene una bandera eliminada, que se usa para ocultar objetos globalmente:
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 predeterminado utilizado por el módulo de administración de Django para incluir conversaciones eliminadas?
django
django-models
django-admin
Natan Yellin
fuente
fuente
Respuestas:
Puede anular el
get_queryset
método en su clase de administrador modelo.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)
Tenga en cuenta que en Django <= 1.5 el método se nombró simplemente
queryset
.fuente
ModelAdmin.queryset
para incluir objetos eliminados? No quiero construir el conjunto de consultas yo mismo en lugar de llamar a la superclase.get_queryset
.Konrad tiene razón, pero esto es más difícil que el ejemplo que se da en la documentación.
Las conversaciones eliminadas no se pueden incluir en un conjunto de consultas que ya las excluye. Así que no veo otra opción que no sea 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
fuente
¿Qué estaría tan mal con lo siguiente?
class Conversation(BaseModel): ... deleted = models.BooleanField(default=False) objects = models.Manager() # includes deleted conversations nondeleted_conversations = NondeletedManager()
Entonces, en sus propias aplicaciones / proyectos, usa
Conversation.nondeleted_conversations()
y deja que la aplicación de administración incorporada haga su trabajo.fuente
La solución aceptada funciona muy bien para mí, pero necesitaba un poco más de flexibilidad, así que terminé extendiendo la vista de la lista de cambios para agregar un parámetro de conjunto de consultas personalizado. Ahora puedo configurar mi conjunto de consultas / filtro predeterminado como tal y aún se puede modificar usando 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)
fuente
Puede hacer esto con un modelo de proxy Django .
# models.py class UnfilteredConversation(Conversation): class Meta: proxy = True # this will be the 'default manager' used in the Admin, and elsewhere objects = models.Manager() # admin.py @admin.register(UnfilteredConversation) class UnfilteredConversationAdmin(Conversation): # regular ModelAdmin stuff here ...
O, si tiene una clase ModelAdmin existente que desea reutilizar:
admin.site.register(UnfilteredConversation, ConversationAdmin)
Este enfoque evita problemas que pueden surgir al anular el administrador predeterminado en el modelo de conversación original, porque el administrador predeterminado también se usa en relaciones ManyToMany y relaciones ForeignKey inversas.
fuente
Natan Yellin tiene razón, pero puede cambiar el orden de los gerentes y el primero será el predeterminado, luego es el que usa el administrador:
class Conversation(BaseModel): ... deleted = models.BooleanField(default=False) all_conversations = models.Manager() # includes deleted conversations objects = NondeletedManager()
La implementación de administración de
get_queryset()
uso._default_manager
en su lugar.objects
, como se muestra a continuaciónqs = self.model._default_manager.get_queryset()
ref Django github Implementación BaseModelAdmin
Esto solo garantiza que cada vez que use YourModel.objects, no incluirá objetos eliminados, sino también las vistas genéricas y otros usos ._default_manager. Entonces, si no anula get_queryset, no es una solución. Acabo de verificar ListView y admin.
fuente