No Django, como verifico se um usuário está em um determinado grupo?


146

Criei um grupo personalizado no site de administração do Django.

No meu código, quero verificar se um usuário está neste grupo. Como faço isso?

Respostas:


117

Você pode acessar os grupos simplesmente através do groupsatributo 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

então user.groups.all()retorna [<Group: Editor>].

Como alternativa e mais diretamente, você pode verificar se um usuário está em um grupo:

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

    ...

Note que tambémgroupname pode ser o objeto atual do Django Group.


112
A verificação real seriaif user.groups.filter(name=group_name).count(): # do something
Maccesch

144
ou usar .exists () em vez de .count ()
Lie Ryan

3
A pergunta é sobre consulta o modelo de usuário para os grupos a que pertence, e não como instantiate'em ... -.-
Jcc.Sanabria

210

Seu objeto Usuário está vinculado ao objeto Grupo por meio de um relacionamento ManyToMany .

Assim, você pode aplicar o método de filtro ao user.groups .

Portanto, para verificar se um determinado usuário está em um determinado grupo ("Membro", por exemplo), faça o seguinte:

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

Se você deseja verificar se um determinado usuário pertence a mais de um grupo, use o operador __in da seguinte forma:

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

Observe que essas funções podem ser usadas com o decorador @user_passes_test para gerenciar o acesso às suas visualizações:

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 esta ajuda


4
Não tenho certeza sobre o funcionamento interno do acesso ao banco de dados do django, mas isso parece muito mais eficiente do que algumas das outras sugestões, como reunir todos os usuários de um grupo e criar um python padrão user in groups(ou vice-versa).
Brianmearns

1
Você não precisa adicionar .exists()no final para retornar um booleano? Caso contrário, is_member()e is_in_multiple_groups()retornará uma QuerySet, o que pode não se obter o resultado desejado.
Michael Bates

4
De acordo com a documentação do Django, é realmente mais rápido para a utilização exista () uma vez que não avaliar os queryset: docs.djangoproject.com/en/dev/ref/models/querysets/#exists
Charlesthk

5
Você provavelmente deseja que o superusuário passe no teste (sem consultar o banco de dados):def is_member(user): return user.is_superuser or user.groups.filter(...
Dave

is_in_multiple_groupspode ser mais explicitamente nomeado is_in_some_groups, uma vez que não requer que o usuário ser um membro de todos os grupos
PeterVermont

15

Se você precisar da lista de usuários que estão em um grupo, faça o seguinte:

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

e depois verifique

 if user in users_in_group:
     # do something

para verificar se o usuário está no grupo.


5
Isso não é adequado para sites com mais de um pequeno número de usuários, pois carrega grandes tabelas de usuários de subconjuntos na memória toda vez que é executado.
bhuber

1
user.groups.filter(name="group name").exists()deve funcionar bem. A solução que você escreveu usa duas consultas e, portanto, não é a ideal.
Noopur Phalak

como se diz, "se você precisar da lista de usuários que estão em um grupo" ...
Mark Chackerian

15

Se você não precisar da instância do usuário no site (como eu fiz), poderá fazê-lo com

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

Isso produzirá apenas uma solicitação para o banco de dados e retornará um booleano.


11

Se um usuário pertence a um determinado grupo ou não, pode ser verificado nos modelos do django usando:

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


1
isso não trabalho para mim, parece que exigem grupo comparar com o nome grupos
Hosein

10

Você só precisa de uma linha:

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
Código não muito limpo e não muito reutilizável, mas +1 por colocá-lo em uma linha.
WhyNotHugo


1

Eu tenho situação semelhante, eu queria testar se o usuário está em um determinado grupo. Então, eu criei um novo arquivo utils.py onde coloco todos os meus pequenos utilitários que me ajudam em todo o aplicativo. Lá, eu tenho essa definição:

utils.py

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

basicamente, estou testando se o usuário está no grupo company_admin e, para maior clareza, chamei essa função de is_company_admin .

Quando quero verificar se o usuário está no company_admin , basta fazer isso:

views.py

from .utils import *

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

Agora, se você deseja testar o mesmo no seu modelo, pode adicionar is_user_admin no seu contexto, algo como isto:

views.py

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

Agora você pode avaliar sua resposta em um modelo:

users.html

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

Solução simples e limpa, com base em respostas que podem ser encontradas anteriormente neste tópico, mas feitas de maneira diferente. Espero que ajude alguém.

Testado no Django 3.0.4.


No seu caso data = Company.objects.all().filter(id=request.user.company.id), o que a Empresa significa? Esse é o seu modelo?
Hayden

Sim @hayden, neste caso a empresa é o meu modelo.
Branko Radojevic

0

Em uma linha:

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

Isso avalia como Trueou False.


3
Isso é ineficiente, pois ele buscará muito mais dados e depois operará no lado do django. É melhor usar .exists()para deixar o banco de dados fazer o trabalho.
WhyNotHugo

0

Eu fiz da seguinte maneira. Parece ineficiente, mas eu não tinha outra maneira de pensar:

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

Essa consulta informará o usuário: "tom" se pertence ao grupo "admin" ou não


groups__name com sublinhado duplo
Trung Lê

0

Eu fiz assim. Para o grupo chamado 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 %}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.