89 votes

Remplacer le queryset par défaut dans l'administration de Django

L'un de mes modèles possède un drapeau supprimé, qui est utilisé pour masquer les objets de manière globale :

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

Comment puis-je remplacer le jeu de requêtes par défaut utilisé par le module d'administration de Django pour inclure les conversations supprimées ?

166voto

Konrad Hałas Points 723

Vous pouvez contourner get_queryset dans la classe d'administration de votre modèle.

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)

Notez que dans Django<=1.5 la méthode était nommée simplement queryset .

10voto

Natan Yellin Points 1427

Konrad a raison, mais c'est plus difficile que l'exemple donné dans la documentation.

Les conversations supprimées ne peuvent pas être incluses dans un queryset qui les exclut déjà. Je ne vois donc pas d'autre option que de réimplémenter entièrement admin.ModelAdmin.queryset.

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

4voto

Evan Porter Points 2128

Qu'est-ce qui serait si mal avec ce qui suit :

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

Dans vos propres applications/projets, vous utilisez donc Conversation.nondeleted_conversations() et laisser l'application d'administration intégrée faire son travail.

4voto

zlovelady Points 2572

Vous pouvez le faire à l'aide d'un fichier Django modèle de substitution .

# 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
    ...

Ou, si vous avez une classe ModelAdmin existante que vous souhaitez réutiliser :

admin.site.register(UnfilteredConversation, ConversationAdmin)

Cette approche permet d'éviter les problèmes qui peuvent se poser en cas de remplacement du gestionnaire par défaut sur le modèle de conversation original, car le gestionnaire par défaut est également utilisé dans les relations ManyToMany et les relations ForeignKey inversées.

2voto

radtek Points 506

La solution acceptée fonctionne très bien pour moi, mais j'avais besoin d'un peu plus de flexibilité, alors j'ai fini par étendre la vue de la liste des modifications pour ajouter un paramètre de queryset personnalisé. Je peux maintenant configurer mon queryset/filtre par défaut comme tel et il peut toujours être modifié en utilisant un filtre différent (paramètres get) :

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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X