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?

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.


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


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.


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.


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 %}


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!")

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

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.


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.


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')

0

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

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


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 %}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.