Django vem com um poderoso sistema de permissão pronto para uso.
Neste artigo, veremos como atribuir permissões a usuários e grupos para autorizá-los a executar ações específicas.
Objetivos
Até o final deste artigo, você poderá:
- Explique como as permissões e grupos de Django funcionam
- Aproveite o poder do sistema de permissão interno do Django
Autenticação vs Autorização
Este artigo trata de autorização.
- Autenticação é o processo de confirmação se um usuário tem acesso a um sistema. Normalmente, um nome de usuário / email e senha são usados para autenticar um usuário.
- Autorização: refere-se ao que o usuário “autenticado” pode fazer em um sistema.
Em outras palavras, a autenticação responde à pergunta ‘quem é você?’ enquanto a autorização responde ‘o que você pode fazer?’.
Permissões a nível de usuário
Quando django.contrib.auth é adicionado ao INSTALLED_APPS
no settings.py, o Django automaticamente cria add
, change
, delete
e view permissions
para cada modelo de Django criado.
As permissões no Django seguem a seguinte sequência de nomes:
{app}.{action}_{model_name}
Notas:
app
é o nome do aplicativo Django em que o modelo associado resideaction
: éadd
,change
,delete
, ouview
model_name
: é o nome do modelo em minúsculas
Vamos supor que temos o seguinte modelo em um aplicativo chamado “blog”:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=400)
body = models.TextField()
Por padrão, o Django criará as seguintes permissões:
blog.add_post
blog.change_post
blog.delete_post
blog.view_post
Você pode verificar se um usuário ( através de um objeto de usuário do Django ) tem permissões com o has_perm()
método:
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User, Permission
from django.contrib.contenttypes.models import ContentType
from blog.models import Post
content_type = ContentType.objects.get_for_model(Post)
post_permission = Permission.objects.filter(content_type=content_type)
print([perm.codename for perm in post_permission])
# => ['add_post', 'change_post', 'delete_post', 'view_post']
user = User.objects.create_user(username="test", password="test", email="[email protected]")
# Check if the user has permissions already
print(user.has_perm("blog.view_post"))
# => False
# To add permissions
for perm in post_permission:
user.user_permissions.add(perm)
print(user.has_perm("blog.view_post"))
# => False
# Why? This is because Django's permissions do not take
# effect until you allocate a new instance of the user.
user = get_user_model().objects.get(email="[email protected]")
print(user.has_perm("blog.view_post"))
# => True
Os superusuários sempre terão permissão definida para True
mesmo que a permissão não exista:
from django.contrib.auth.models import User
superuser = User.objects.create_superuser(
username="super", password="test", email="[email protected]"
)
# Output will be true
print(superuser.has_perm("blog.view_post"))
# Output will be true even if the permission does not exists
print(superuser.has_perm("foo.add_bar"))
Um superusuário é um tipo de usuário no Django que possui todas as permissões no sistema. Sejam permissões personalizadas ou permissões criadas pelo Django, os superusuários têm acesso a todas as permissões.
Um usuário da equipe é como qualquer outro usuário do seu sistema, MAS com a vantagem adicional de poder acessar a interface do Django Admin. A interface do Django Admin é acessível apenas para superusuários e usuários da equipe.
Permissões em nível de grupo
Ter que atribuir permissões de cada vez aos usuários é tedioso e não escalável. Pode haver casos em que você deseja adicionar novas permissões a um conjunto de usuários. Aqui é onde Grupos Django entre em jogo.
O que é um grupo?
- Definição em inglês: um grupo é um conjunto de objetos classificados juntos.
- Definição de Django: Os modelos de grupo são uma maneira genérica de categorizar usuários, para que você possa aplicar permissões ou algum outro rótulo a esses usuários. Um usuário pode pertencer a qualquer número de grupos.
Com o Django, você pode criar grupos para usuários de classe e atribuir permissões a cada grupo; portanto, ao criar usuários, você pode simplesmente atribuir o usuário a um grupo e, por sua vez, o usuário tem todas as permissões desse grupo.
Para criar um grupo, você precisa do Group
modelo de django.contrib.auth.models
.
Vamos criar grupos para os seguintes papéis:
Author
: Pode visualizar e adicionar postagensEditor
: Pode visualizar, adicionar e editar postagensPublisher
: Pode visualizar, adicionar, editar e excluir postagens
Código:
from django.contrib.auth.models import Group, User, Permission
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404
from blog.models import Post
author_group, created = Group.objects.get_or_create(name="Author")
editor_group, created = Group.objects.get_or_create(name="Editor")
publisher_group, created = Group.objects.get_or_create(name="Publisher")
content_type = ContentType.objects.get_for_model(Post)
post_permission = Permission.objects.filter(content_type=content_type)
print([perm.codename for perm in post_permission])
# => ['add_post', 'change_post', 'delete_post', 'view_post']
for perm in post_permission:
if perm.codename == "delete_post":
publisher_group.permissions.add(perm)
elif perm.codename == "change_post":
editor_group.permissions.add(perm)
publisher_group.permissions.add(perm)
else:
author_group.permissions.add(perm)
editor_group.permissions.add(perm)
publisher_group.permissions.add(perm)
user = User.objects.get(username="test")
user.groups.add(author_group) # Add the user to the Author group
user = get_object_or_404(User, pk=user.id)
print(user.has_perm("blog.delete_post")) # => False
print(user.has_perm("blog.change_post")) # => False
print(user.has_perm("blog.view_post")) # => True
print(user.has_perm("blog.add_post")) # => True
Execução de permissões
Além do Django Admin, as permissões geralmente são aplicadas na camada de visualização, pois o usuário é obtido do objeto de solicitação.
Para impor permissões em visualizações baseadas em classe, você pode usar o PermissãoRequiredMixin de django.contrib.auth.mixins
assim:
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.views.generic import ListView
from blog.models import Post
class PostListView(PermissionRequiredMixin, ListView):
permission_required = "blog.view_post"
template_name = "post.html"
model = Post
permission_required
pode ser uma permissão única ou uma iterável permissão. Se estiver usando um iterável, o usuário deverá ter TODAS as permissões antes de poder acessar a visualização:
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.views.generic import ListView
from blog.models import Post
class PostListView(PermissionRequiredMixin, ListView):
permission_required = ("blog.view_post", "blog.add_post")
template_name = "post.html"
model = Post
Para visualizações baseadas em funções, use o permission_required
decorador:
from django.contrib.auth.decorators import permission_required
@permission_required("blog.view_post")
def post_list_view(request):
return HttpResponse()
Você também pode verificar se há permissões nos modelos do Django. Com os processadores de contexto de autenticação do Django, um perms variável está disponível por padrão quando você renderiza seu modelo. O perms
variável realmente contém todas as permissões no seu aplicativo Django.
Por exemplo:
{% if perms.blog.view_post %}
{# Your content here #}
{% endif %}
Permissões no nível do modelo
Você também pode adicionar permissões personalizadas a um modelo Django através do modelo Meta opções.
Vamos adicionar um is_published
bandeira para o Post
modelo:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=400)
body = models.TextField()
is_published = models.Boolean(default=False)
Em seguida, definiremos uma permissão personalizada chamada set_published_status
:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=400)
body = models.TextField()
is_published = models.Boolean(default=False)
class Meta:
permissions = [
(
"set_published_status",
"Can set the status of the post to either publish or not"
)
]
Para impor essa permissão, podemos usar o UserPassesTestMixin
O Django forneceu mixin em nossa opinião, dando-nos a flexibilidade de verificar explicitamente se um usuário tem a permissão necessária ou não.
Aqui está o que uma visualização baseada em classe pode parecer que verifica se um usuário tem permissão para definir o status publicado de uma postagem:
from django.contrib.auth.mixins import UserPassesTestMixin
from django.shortcuts import render
from django.views.generic import View
from blog.models import Post
class PostListView(UserPassesTestMixin, View):
template_name = "post_details.html"
def test_func(self):
return self.request.user.has_perm("blog.set_published_status")
def post(self, request, *args, **kwargs):
post_id = request.POST.get('post_id')
published_status = request.POST.get('published_status')
if post_id:
post = Post.objects.get(pk=post_id)
post.is_published = bool(published_status)
post.save()
return render(request, self.template_name)
Então, com UserPassesTestMixin
, você precisa substituir o test_func
método da classe e adicione seu próprio teste. Observe que o valor de retorno desse método deve sempre ser um booleano.
Permissões no nível do objeto
Se você estiver usando o Django REST Framework, ele já possui permissões no nível do objeto incorporado à classe de permissão básica. BasePermission
tem has_permission
, que é basicamente para visualizações de lista e has_object_permission
, que verifica se o usuário tem permissão para acessar uma única instância de modelo.
Para mais informações sobre permissões no Django REST Framework, reveja Permissões no Django REST Framework.
Se você não estiver usando o Django REST Framework, para implementar permissões no nível do objeto, poderá usar terceiros, como:
Para mais pacotes relacionados a permissões, confira Pacotes Django.
Conclusão
Neste artigo, você aprendeu a adicionar permissões a um modelo Django e a verificar se há permissões. Se você tiver um número definido de tipos de usuário, poderá criar cada tipo de usuário como um grupo e fornecer as permissões necessárias ao grupo. Então, para cada usuário adicionado ao sistema e ao grupo necessário, as permissões são concedidas automaticamente a cada usuário.