En Django, ¿cómo verifico si un usuario está en un determinado grupo?

147

Creé un grupo personalizado en el sitio de administración de Django.

En mi código, quiero verificar si un usuario está en este grupo. ¿Cómo puedo hacer eso?

TIMEX
fuente

Respuestas:

118

Puede acceder a los grupos simplemente a través del groupsatributo activado 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

Luego user.groups.all()regresa [<Group: Editor>].

Alternativamente, y más directamente, puede verificar si un usuario está en un grupo:

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

    ...

Tenga en cuenta que tambiéngroupname puede ser el objeto real del Grupo Django.

miku
fuente
112
La comprobación real seríaif user.groups.filter(name=group_name).count(): # do something
Maccesch
144
o use .exists () en lugar de .count ()
Lie Ryan
3
La pregunta es sobre consultar el modelo de Usuario para los grupos a los que pertenece, no cómo instanciarlos ... -.-
Jcc.Sanabria
210

Su objeto Usuario está vinculado al objeto Grupo a través de una relación ManyToMany .

De este modo, puede aplicar el método de filtro a user.groups .

Entonces, para verificar si un Usuario dado está en un grupo determinado ("Miembro" para el ejemplo), simplemente haga esto:

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

Si desea verificar si un usuario dado pertenece a más de un grupo dado, use el operador __in de la siguiente manera:

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

Tenga en cuenta que esas funciones se pueden usar con el decorador @user_passes_test para administrar el acceso a sus vistas:

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

Espero que esto ayude

Charlesthk
fuente
44
No estoy seguro sobre el funcionamiento interno del acceso a la base de datos de django, pero esto parece mucho más eficiente que algunas de las otras sugerencias, como reunir a todos los usuarios en un grupo y hacer un pitón estándar user in groups(o viceversa).
brianmearns
1
¿No tienes que agregar .exists()al final para devolver un booleano? De lo contrario is_member(), y is_in_multiple_groups()devolverá una QuerySet, que puede no dar el resultado deseado.
Michael Bates
44
De acuerdo con la documentación de Django, es más rápido usar existe () ya que no evalúa el conjunto de consultas: docs.djangoproject.com/en/dev/ref/models/querysets/#exists
Charlesthk
55
Probablemente desee que el superusuario pase la prueba (sin consultar la base de datos):def is_member(user): return user.is_superuser or user.groups.filter(...
Dave
is_in_multiple_groupspuede ser nombrado más explícitamente is_in_some_groupsya que no requiere que el usuario sea miembro de todos los grupos
PeterVermont
15

Si necesita la lista de usuarios que están en un grupo, puede hacer esto en su lugar:

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

y luego verifica

 if user in users_in_group:
     # do something

para verificar si el usuario está en el grupo.

Mark Chackerian
fuente
55
Esto no escala bien para sitios con más de un pequeño número de usuarios, ya que cargará una tabla de usuarios de subconjuntos grandes en la memoria cada vez que se ejecute.
bhuber
1
user.groups.filter(name="group name").exists()Debería funcionar bien. La solución que ha escrito utiliza dos consultas y, por lo tanto, no es muy óptima.
Noopur Phalak
como dice, "si necesita la lista de usuarios que están en un grupo" ...
Mark Chackerian
15

Si no necesita la instancia de usuario en el sitio (como yo lo hice), puede hacerlo con

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

Esto producirá solo una solicitud a la base de datos y devolverá un valor booleano.

David Kühner
fuente
11

Si un usuario pertenece a un determinado grupo o no, se puede verificar en las plantillas de django usando:

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

CÓDIGO
fuente
1
esto no funciona para mí, parece que requieren comparar el grupo con el nombre del grupo
hosein
10

Solo necesitas una línea:

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
fuente
44
Sin embargo, no es un código muy limpio y no es muy reutilizable, pero +1 para ponerlo en una línea.
WhyNotHugo
1

En caso de que si desea verificar que el grupo de usuarios pertenezca a una lista de grupos predefinida:

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
fuente
1

Tengo una situación similar, quería probar si el usuario está en un determinado grupo. Entonces, he creado un nuevo archivo utils.py donde pongo todas mis pequeñas utilidades que me ayudan a través de toda la aplicación. Ahí tengo esta definición:

utils.py

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

así que básicamente estoy probando si el usuario está en el grupo company_admin y para mayor claridad he llamado a esta función is_company_admin .

Cuando quiero comprobar si el usuario está en el company_admin acabo de hacer esto:

views.py

from .utils import *

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

Ahora, si desea probar lo mismo en su plantilla, puede agregar is_user_admin en su contexto, algo como esto:

views.py

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

Ahora puede evaluar su respuesta en una plantilla:

users.html

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

Solución simple y limpia, basada en respuestas que se pueden encontrar anteriormente en este hilo, pero que se hacen de manera diferente. Espero que ayude a alguien.

Probado en Django 3.0.4.

Branko Radojevic
fuente
En su data = Company.objects.all().filter(id=request.user.company.id), ¿qué significa la Compañía? ¿Es ese tu modelo?
Hayden
Sí @hayden, en este caso, la empresa es mi modelo.
Branko Radojevic
0

En una línea:

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

Esto se evalúa como Trueo False.

Philipp Zedler
fuente
3
Esto es ineficiente, ya que obtendrá muchos más datos y luego operará en el lado de Django. Es mejor usar .exists()para dejar que el db haga el trabajo.
WhyNotHugo
0

Lo he hecho de la siguiente manera. Parece ineficiente pero no tenía otra forma en mi mente:

@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
fuente
0

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

Esa consulta le informará al usuario: "tom" si pertenece al grupo "admin" o no

Trung Lê
fuente
groups__name con guión bajo doble
Trung Lê
0

Lo hice así. Para el grupo nombrado 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)

modelo

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