Dans Django, comment vérifier si un utilisateur fait partie d'un certain groupe?


147

J'ai créé un groupe personnalisé sur le site d'administration de Django.

Dans mon code, je veux vérifier si un utilisateur fait partie de ce groupe. Comment je fais ça?

Réponses:


118

Vous pouvez accéder aux groupes simplement via l' groupsattribut sur User.

from django.contrib.auth.models import User, Group

group = Group(name = "Editor")
group.save()                    # save this new group for this example
user = User.objects.get(pk = 1) # assuming, there is one initial user 
user.groups.add(group)          # user is now in the "Editor" group

puis user.groups.all()revient [<Group: Editor>].

Alternativement, et plus directement, vous pouvez vérifier si un utilisateur est dans un groupe en:

if django_user.groups.filter(name = groupname).exists():

    ...

Notez qu'il groupnamepeut également s'agir de l'objet Django Group réel.


112
La vérification réelle seraitif user.groups.filter(name=group_name).count(): # do something
Maccesch

144
ou utilisez .exists () au lieu de .count ()
Lie Ryan

3
La question est d'interroger le modèle User pour les groupes auxquels il appartient, pas de savoir comment l'instancier ... -.-
Jcc.Sanabria

210

Votre objet User est lié à l' objet Group via une relation ManyToMany .

Vous pouvez ainsi appliquer la méthode de filtrage à user.groups .

Donc, pour vérifier si un utilisateur donné est dans un certain groupe ("Membre" pour l'exemple), il suffit de faire ceci:

def is_member(user):
    return user.groups.filter(name='Member').exists()

Si vous voulez vérifier si un utilisateur donné appartient à plus d'un groupe donné, utilisez l' opérateur __in comme ceci:

def is_in_multiple_groups(user):
    return user.groups.filter(name__in=['group1', 'group2']).exists()

Notez que ces fonctions peuvent être utilisées avec le décorateur @user_passes_test pour gérer l'accès à vos vues:

from django.contrib.auth.decorators import login_required, user_passes_test
@login_required
@user_passes_test(is_member) # or @user_passes_test(is_in_multiple_groups)
def myview(request):
    # Do your processing

J'espère que cette aide


4
Je ne suis pas sûr du fonctionnement interne de l'accès à la base de données de django, mais cela semble beaucoup plus efficace que certaines des autres suggestions, comme rassembler tous les utilisateurs dans un groupe et faire un python standard user in groups(ou vice versa).
brianmearns

1
N'avez-vous pas besoin d'ajouter .exists()à la fin pour renvoyer un booléen? Sinon, is_member()et is_in_multiple_groups()renverra a QuerySet, ce qui risque de ne pas donner le résultat souhaité.
Michael Bates

4
D'après la documentation de Django, il est en effet plus rapide d'utiliser exist () car il n'évalue pas l'ensemble de requêtes: docs.djangoproject.com/en/dev/ref/models/querysets/#exists
Charlesthk

5
Vous voulez probablement que le super-utilisateur réussisse le test (sans interroger la base de données):def is_member(user): return user.is_superuser or user.groups.filter(...
Dave

is_in_multiple_groupspeut être nommé plus explicitement is_in_some_groupscar il ne nécessite pas que l'utilisateur soit membre de tous les groupes
PeterVermont

15

Si vous avez besoin de la liste des utilisateurs appartenant à un groupe, vous pouvez le faire à la place:

from django.contrib.auth.models import Group
users_in_group = Group.objects.get(name="group name").user_set.all()

puis vérifiez

 if user in users_in_group:
     # do something

pour vérifier si l'utilisateur fait partie du groupe.


5
Cela ne s'adapte pas bien aux sites comptant plus d'un petit nombre d'utilisateurs, car il chargera en mémoire de grands sous-ensembles de la table des utilisateurs à chaque exécution.
bhuber

1
user.groups.filter(name="group name").exists()devrait bien fonctionner. La solution que vous avez écrite utilise deux requêtes et donc pas très optimale.
Noopur Phalak

comme il dit, "si vous avez besoin de la liste des utilisateurs qui sont dans un groupe" ...
Mark Chackerian

15

Si vous n'avez pas besoin de l'instance utilisateur sur le site (comme je l'ai fait), vous pouvez le faire avec

User.objects.filter(pk=userId, groups__name='Editor').exists()

Cela produira une seule requête à la base de données et retournera un booléen.


11

Si un utilisateur appartient ou non à un certain groupe, peut être vérifié dans les modèles django en utilisant:

{% if group in request.user.groups.all %} "some action" {% endif %}


1
cela ne fonctionne pas pour moi, semble nécessiter de comparer le groupe avec le nom du groupe
hosein

10

Vous avez juste besoin d'une ligne:

from django.contrib.auth.decorators import user_passes_test  

@user_passes_test(lambda u: u.groups.filter(name='companyGroup').exists())
def you_view():
    return HttpResponse("Since you're logged in, you can see this text!")

4
Code pas très propre cependant, et pas très réutilisable, mais +1 pour le mettre en une seule ligne.
WhyNotHugo

1

Juste au cas où vous voudriez vérifier que le groupe de l'utilisateur appartient à une liste de groupes prédéfinie:

def is_allowed(user):
    allowed_group = set(['admin', 'lead', 'manager'])
    usr = User.objects.get(username=user)
    groups = [ x.name for x in usr.groups.all()]
    if allowed_group.intersection(set(groups)):
       return True
    return False


1

J'ai une situation similaire, je voulais tester si l'utilisateur est dans un certain groupe. J'ai donc créé un nouveau fichier utils.py dans lequel j'ai mis tous mes petits utilitaires qui m'aident à travers toute l'application. Là, j'ai cette définition:

utils.py

def is_company_admin(user):
    return user.groups.filter(name='company_admin').exists()

Donc, fondamentalement, je teste si l'utilisateur est dans le groupe company_admin et pour plus de clarté, j'ai appelé cette fonction is_company_admin .

Lorsque je veux vérifier si l'utilisateur est dans company_admin, je fais simplement ceci:

views.py

from .utils import *

if is_company_admin(request.user):
        data = Company.objects.all().filter(id=request.user.company.id)

Maintenant, si vous souhaitez tester la même chose dans votre modèle, vous pouvez ajouter is_user_admin dans votre contexte, quelque chose comme ceci:

views.py

return render(request, 'admin/users.html', {'data': data, 'is_company_admin': is_company_admin(request.user)})

Vous pouvez maintenant évaluer votre réponse dans un modèle:

users.html

{% if is_company_admin %}
     ... do something ...
{% endif %}

Solution simple et propre, basée sur des réponses qui peuvent être trouvées plus tôt dans ce fil, mais faites différemment. J'espère que cela aidera quelqu'un.

Testé dans Django 3.0.4.


Dans votre data = Company.objects.all().filter(id=request.user.company.id), que signifie Entreprise? Est-ce votre modèle?
Hayden le

Oui @hayden, dans ce cas, Company est mon modèle.
Branko Radojevic

0

En une seule ligne:

'Groupname' in user.groups.values_list('name', flat=True)

Cela évalue soit Trueou False.


3
Ceci est inefficace, car il va chercher beaucoup plus de données, puis opérer dessus du côté de django. Il vaut mieux l'utiliser .exists()pour laisser la base de données faire le travail.
WhyNotHugo

0

Je l'ai fait de la manière suivante. Cela semble inefficace mais je n'avais pas d'autre moyen dans mon esprit:

@login_required
def list_track(request):

usergroup = request.user.groups.values_list('name', flat=True).first()
if usergroup in 'appAdmin':
    tracks = QuestionTrack.objects.order_by('pk')
    return render(request, 'cmit/appadmin/list_track.html', {'tracks': tracks})

else:
    return HttpResponseRedirect('/cmit/loggedin')

0

User.objects.filter(username='tom', groups__name='admin').exists()

Cette requête vous informera de l'utilisateur: "tom", qu'il appartienne ou non au groupe "admin"


groups__name avec double souligné
Trung Lê

0

Je l'ai fait comme ça. Pour le groupe nommé Editor.

# views.py
def index(request):
    current_user_groups = request.user.groups.values_list("name", flat=True)
    context = {
        "is_editor": "Editor" in current_user_groups,
    }
    return render(request, "index.html", context)

modèle

# index.html
{% if is_editor %}
  <h1>Editor tools</h1>
{% endif %}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.