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.