In Django, come posso verificare se un utente appartiene a un determinato gruppo?


147

Ho creato un gruppo personalizzato nel sito di amministrazione di Django.

Nel mio codice, voglio verificare se un utente è in questo gruppo. Come lo faccio?

Risposte:


118

Puoi accedere ai gruppi semplicemente tramite l' groupsattributo on 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

quindi user.groups.all()ritorna [<Group: Editor>].

In alternativa, e più direttamente, puoi verificare se un utente è in un gruppo:

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

    ...

Nota che groupnamepuò essere anche l'oggetto reale del gruppo Django.


112
Il controllo effettivo sarebbeif user.groups.filter(name=group_name).count(): # do something
Maccesch,

144
oppure usa .exists () invece di .count ()
Lie Ryan,

3
La domanda riguarda l'interrogazione del modello utente per i gruppi di appartenenza, non come istanziarli ... -.-
Jcc.Sanabria

210

L' oggetto Utente è collegato all'oggetto Gruppo tramite una relazione ManyToMany .

È quindi possibile applicare il metodo di filtro a user.groups .

Quindi, per verificare se un determinato Utente appartiene a un determinato gruppo ("Membro" per l'esempio), basta fare questo:

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

Se si desidera verificare se un determinato utente appartiene a più di un determinato gruppo, utilizzare l' operatore __in in questo modo:

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

Nota che queste funzioni possono essere utilizzate con il decoratore @user_passes_test per gestire l'accesso alle tue viste:

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

Spero che questo aiuto


4
Non sono sicuro del funzionamento interno dell'accesso al DB di django, ma questo sembra molto più efficiente di alcuni altri suggerimenti, come mettere tutti gli utenti in un gruppo e fare un pitone standard user in groups(o viceversa).
brianmearns,

1
Non è necessario aggiungere .exists()alla fine per restituire un valore booleano? Altrimenti is_member()e is_in_multiple_groups()restituirà a QuerySet, che potrebbe non dare il risultato desiderato.
Michael Bates,

4
Secondo la documentazione di Django, è effettivamente più veloce usare esiste () poiché non valuta il queryset
Charlesthk,

5
Probabilmente vuoi che il superutente superi il test (senza interrogare il database):def is_member(user): return user.is_superuser or user.groups.filter(...
Dave,

is_in_multiple_groupspuò essere nominato in modo più esplicito is_in_some_groupspoiché non richiede che l'utente sia membro di tutti i gruppi
PeterVermont

15

Se hai bisogno dell'elenco di utenti che fanno parte di un gruppo, puoi invece farlo:

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

e poi controlla

 if user in users_in_group:
     # do something

per verificare se l'utente è nel gruppo.


5
Questo non si adatta bene ai siti con più di un numero limitato di utenti, poiché caricherà in memoria tabelle di utenti di sottoinsiemi ogni volta che viene eseguito.
bhuber,

1
user.groups.filter(name="group name").exists()dovrebbe funzionare bene. La soluzione che hai scritto utilizza due query e quindi non molto ottimali.
Noopur Phalak,

come dice "se hai bisogno dell'elenco degli utenti che fanno parte di un gruppo" ...
Mark Chackerian,

15

Se non hai bisogno dell'istanza utente sul sito (come ho fatto io), puoi farlo con

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

Ciò produrrà una sola richiesta al database e restituirà un valore booleano.


11

Se un utente appartiene o meno a un determinato gruppo, può essere verificato nei modelli di django usando:

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


1
questo non funziona per me, sembra che richieda un confronto tra il gruppo e il nome del gruppo
hosein

10

Hai solo bisogno di una riga:

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
Tuttavia, il codice non è molto pulito e non è molto riutilizzabile, ma +1 per inserirlo in una riga.
WhyNotHugo,

1

Nel caso in cui si desideri verificare che il gruppo dell'utente appartenga a un elenco di gruppi predefinito:

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

Ho una situazione simile, volevo verificare se l'utente appartiene a un determinato gruppo. Quindi, ho creato un nuovo file utils.py dove ho inserito tutte le mie piccole utility che mi aiutano attraverso l'intera applicazione. Ecco, ho questa definizione:

utils.py

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

quindi sostanzialmente sto testando se l'utente è nel gruppo company_admin e per chiarezza ho chiamato questa funzione is_company_admin .

Quando voglio verificare se l'utente è in company_admin, faccio solo questo:

views.py

from .utils import *

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

Ora, se desideri provare lo stesso nel tuo modello, puoi aggiungere is_user_admin nel tuo contesto, qualcosa del genere:

views.py

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

Ora puoi valutare la tua risposta in un modello:

users.html

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

Soluzione semplice e pulita, basata su risposte che possono essere trovate in precedenza in questo thread, ma fatte in modo diverso. Spero che possa aiutare qualcuno.

Testato in Django 3.0.4.


Nel tuo data = Company.objects.all().filter(id=request.user.company.id), cosa significa Azienda? È quello il tuo modello?
Hayden,

Sì @hayden, in questo caso la società è il mio modello.
Branko Radojevic,

0

In una riga:

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

Questo valuta uno Trueo False.


3
Questo è inefficiente, dal momento che recupererà molti più dati, e quindi opererà su di esso da parte di Django. È meglio usare .exists()per lasciare che il db faccia il lavoro.
WhyNotHugo,

0

L'ho fatto nel modo seguente. Sembra inefficiente ma non avevo altro modo di pensare:

@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()

Quella query informerà l'utente: "tom" se appartiene o meno al gruppo "admin"


groups__name con doppio trattino basso
Trung Lê

0

L'ho fatto così. Per il gruppo denominato 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)

modello

# index.html
{% if is_editor %}
  <h1>Editor tools</h1>
{% endif %}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.