48 votes

Django Admin - Contenu utilisateur (admin) spécifique

Je commence à organiser un nouveau projet, et disons que je vais avoir quelques modèles comme les produits et catalogues.

Je vais permettre à mes clients (pas les visiteurs, des clients spécifiques) pour vous connecter sur le site d'administration de Django de créer, de modifier et de supprimer leurs propres catalogues.

Disons que j'ai créer un modèle appelé "Boutique", créer chaque magasin (nom, adresse, logo, coordonnées, etc...) et créer un utilisateur admin " lié " à la boutique.

Maintenant, je veux cette nouvelle admin (qui n'est pas un administrateur du site, mais une boutique admin -- probablement un groupe d'utilisateurs) pour voir et modifier uniquement les catalogues en lien avec sa boutique.

Est-ce possible?

Dois-je le faire à l'intérieur de l'Django Admin ou devrais-je créer une nouvelle "boutique admin" application?

60voto

Chris Pratt Points 53859

Tout d'abord, la mise en garde: Le Django admin philosophie de conception est que tout utilisateur disposant d'un accès à l'admin (is_staff==True) est une confiance de l'utilisateur, par exemple un employé, d'où le "personnel" de la désignation de même accéder à l'admin. Alors que vous pouvez personnaliser à l'administrateur de restreindre les zones, permettant à quiconque de ne pas l'intérieur de votre organisation un accès à votre administrateur est considéré comme risqué, et Django ne fait aucune garantie de toute sorte de sécurité à ce point.

Maintenant, si vous voulez continuer, vous pouvez limiter la plupart des tout le mais les magasins dès le départ, tout simplement en n'attribuant ces privilèges à l'utilisateur. Vous aurez à donner à tous les propriétaires de magasin de droits pour modifier l'un de la boutique, modèles, ils auront besoin de l'accès à l', mais tout le reste doit être laissé sur leur liste d'autorisations.

Ensuite, pour chaque modèle doit être limitée à la propriétaire yeux seulement, vous aurez besoin d'ajouter un champ pour stocker le "propriétaire", ou de l'utilisateur autorisé à accéder à elle. Vous pouvez faire cela avec l' save_model méthode ModelAdmin, qui a accès à l'objet de la requête:

class MyModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.user = request.user
        super(MyModelAdmin, self).save_model(request, obj, form, change)

Ensuite, vous aurez besoin aussi de limiter l'ModelAdmin du queryset pour que les éléments propres à l'utilisateur actuel:

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

Toutefois, cela ne limite ce qui est listé, l'utilisateur pourrait encore jouer avec l'URL pour accéder à d'autres objets qu'ils n'ont pas accès à l', de sorte que vous aurez besoin de remplacer chacun des ModelAdmin les plus vulnérables de vue de rediriger si l'utilisateur n'est pas le propriétaire:

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

class MyModelAdmin(admin.ModelAdmin):
    def change_view(self, request, object_id, form_url='', extra_context=None):
        if not self.queryset(request).filter(id=object_id).exists():
            return HttpResponseRedirect(reverse('admin:myapp_mymodel_changelist'))

        return super(MyModelAdmin, self).change_view(request, object_id, form_url, extra_context)

    def delete_view(self, request, object_id, extra_context=None):
        if not self.queryset(request).filter(id=object_id).exists():
            return HttpResponseRedirect(reverse('admin:myapp_mymodel_changelist'))

        return super(MyModelAdmin, self).delete_view(request, object_id, extra_context)

    def history_view(self, request, object_id, extra_context=None):
        if not self.queryset(request).filter(id=object_id).exists():
            return HttpResponseRedirect(reverse('admin:myapp_mymodel_changelist'))

        return super(MyModelAdmin, self).history_view(request, object_id, extra_context)

Mise à JOUR 06/05/12

Merci @christophe31 pour souligner que, depuis l' ModelAdmins'queryset est déjà limitée par l'utilisateur, vous pouvez simplement utiliser self.queryset() de la modifier, de supprimer et d'histoire de point de vue. Ce bien résumés de loin le modèle classname rendre le code moins fragile. J'ai aussi changé à l'aide d' filter et exists au lieu de try...except bloc get. C'est plus rationnelle de cette façon, et donne lieu à une requête plus simple ainsi.

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