Wie überprüfe ich in Django, ob sich ein Benutzer in einer bestimmten Gruppe befindet?

146

Ich habe eine benutzerdefinierte Gruppe auf der Administrationsseite von Django erstellt.

In meinem Code möchte ich überprüfen, ob sich ein Benutzer in dieser Gruppe befindet. Wie mache ich das?

TIMEX
quelle

Antworten:

117

Sie können einfach über das groupsAttribut auf auf die Gruppen zugreifen 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

user.groups.all()kehrt dann zurück [<Group: Editor>].

Alternativ und direkter können Sie überprüfen, ob sich ein Benutzer in einer Gruppe befindet, indem Sie:

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

    ...

Beachten Sie, dass groupnamedies auch das eigentliche Django Group-Objekt sein kann.

miku
quelle
112
Die eigentliche Überprüfung wäreif user.groups.filter(name=group_name).count(): # do something
Maccesch
144
oder verwenden Sie .exists () anstelle von .count ()
Lie Ryan
3
Bei der Frage geht es darum, das Benutzermodell nach den Gruppen abzufragen, zu denen es gehört, und nicht darum, wie man sie instanziiert ... -.-
Jcc.Sanabria
210

Ihr Benutzerobjekt wird mit dem verknüpften Gruppe Objekt durch eine ManyToMany Beziehung.

Sie können damit die Filtermethode auf user.groups anwenden .

Um zu überprüfen, ob sich ein bestimmter Benutzer in einer bestimmten Gruppe befindet (im Beispiel "Mitglied"), gehen Sie wie folgt vor:

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

Wenn Sie überprüfen möchten, ob ein bestimmter Benutzer zu mehr als einer bestimmten Gruppe gehört, verwenden Sie den Operator __in wie folgt :

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

Beachten Sie, dass diese Funktionen mit dem Dekorator @user_passes_test verwendet werden können , um den Zugriff auf Ihre Ansichten zu verwalten:

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

Ich hoffe das hilft

Charlesthk
quelle
4
Ich bin mir nicht sicher, wie der DB-Zugriff von Django funktioniert, aber dies scheint viel effizienter zu sein als einige der anderen Vorschläge, z. B. alle Benutzer in eine Gruppe zu bringen und eine Standard-Python zu erstellen user in groups(oder umgekehrt).
Brianmearns
1
Müssen Sie nicht .exists()am Ende hinzufügen , um einen Booleschen Wert zurückzugeben? Andernfalls is_member()und is_in_multiple_groups()eine Rückkehr QuerySet, die nicht das gewünschte Ergebnis geben kann.
Michael Bates
4
Laut der Dokumentation von Django ist die Verwendung von exist () tatsächlich schneller, da das Abfrageset nicht ausgewertet wird: docs.djangoproject.com/en/dev/ref/models/querysets/#exists
Charlesthk
5
Sie möchten wahrscheinlich, dass der Superuser den Test besteht (ohne die Datenbank abzufragen):def is_member(user): return user.is_superuser or user.groups.filter(...
Dave
is_in_multiple_groupskann expliziter benannt werden, is_in_some_groupsda der Benutzer nicht Mitglied aller Gruppen sein muss
PeterVermont
15

Wenn Sie die Liste der Benutzer in einer Gruppe benötigen, können Sie dies folgendermaßen tun:

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

und dann überprüfen

 if user in users_in_group:
     # do something

um zu überprüfen, ob der Benutzer in der Gruppe ist.

Mark Chackerian
quelle
5
Dies lässt sich für Websites mit mehr als einer kleinen Anzahl von Benutzern nicht gut skalieren, da bei jeder Ausführung große Teilmengen der Benutzertabelle in den Speicher geladen werden.
Bhuber
1
user.groups.filter(name="group name").exists()sollte gut funktionieren. Die von Ihnen geschriebene Lösung verwendet zwei Abfragen und ist daher nicht sehr optimal.
Noopur Phalak
wie es heißt, "wenn Sie die Liste der Benutzer benötigen, die zu einer Gruppe gehören" ...
Mark Chackerian
15

Wenn Sie die Benutzerinstanz nicht vor Ort benötigen (wie ich), können Sie dies tun

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

Dies erzeugt nur eine Anforderung an die Datenbank und gibt einen Booleschen Wert zurück.

David Kühner
quelle
11

Ob ein Benutzer einer bestimmten Gruppe angehört oder nicht, kann in Django-Vorlagen überprüft werden mit:

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

CODEkid
quelle
1
Dies funktioniert nicht für mich, scheint, dass erfordern Vergleich Gruppe mit Gruppennamen
Hosein
10

Sie brauchen nur eine Zeile:

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!")
Marcelo Cintra de Melo
quelle
4
Nicht sehr sauberer Code und nicht sehr wiederverwendbar, aber +1, um ihn in eine Zeile zu bringen.
WhyNotHugo
1

Nur für den Fall, dass Sie überprüfen möchten, ob die Benutzergruppe zu einer vordefinierten Gruppenliste gehört:

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
James Sapam
quelle
1

Ich habe eine ähnliche Situation, ich wollte testen, ob der Benutzer in einer bestimmten Gruppe ist. Also habe ich eine neue Datei utils.py erstellt, in der ich alle meine kleinen Dienstprogramme ablege, die mir bei der gesamten Anwendung helfen. Dort habe ich diese Definition:

utils.py

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

Im Grunde teste ich, ob sich der Benutzer in der Gruppe company_admin befindet, und aus Gründen der Übersichtlichkeit habe ich diese Funktion is_company_admin genannt .

Wenn ich überprüfen möchte, ob sich der Benutzer in der Datei company_admin befindet, gehe ich einfach folgendermaßen vor:

views.py

from .utils import *

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

Wenn Sie dasselbe in Ihrer Vorlage testen möchten, können Sie is_user_admin in Ihrem Kontext hinzufügen.

views.py

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

Jetzt können Sie Ihre Antwort in einer Vorlage auswerten:

users.html

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

Einfache und saubere Lösung, basierend auf Antworten, die früher in diesem Thread zu finden sind, aber anders gemacht werden. Hoffe es wird jemandem helfen.

Getestet in Django 3.0.4.

Branko Radojevic
quelle
data = Company.objects.all().filter(id=request.user.company.id)Was bedeutet das Unternehmen in Ihrem Unternehmen? Ist das dein Model?
Hayden
Ja @hayden, in diesem Fall ist Firma mein Modell.
Branko Radojevic
0

In einer Zeile:

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

Dies ergibt entweder Trueoder False.

Philipp Zedler
quelle
3
Dies ist ineffizient, da viel mehr Daten abgerufen und dann auf Djangos Seite bearbeitet werden. Es ist besser .exists(), die Datenbank die Arbeit machen zu lassen.
WhyNotHugo
0

Ich habe es folgendermaßen gemacht. Scheint ineffizient, aber ich hatte keinen anderen Weg im Kopf:

@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')
Mohammad
quelle
0

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

Diese Abfrage informiert den Benutzer: "tom", ob er zur Gruppe "admin" gehört oder nicht

Trung Lê
quelle
Gruppen__name mit doppeltem Unterstrich
Trung Lê
0

Ich habe es so gemacht. Für die Gruppe mit dem Namen 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)

Vorlage

# index.html
{% if is_editor %}
  <h1>Editor tools</h1>
{% endif %}
Harry Moreno
quelle