O documento descreve o sistema de permissões padrão do Django (django.contrib.auth), que permite atribuir permissões de can_change, can_add e can_delete a usuários e grupos para modelos habilitados. As permissões podem ser atribuídas no admin ou programaticamente e são verificadas em views e templates através de has_perm.
2. Algumas definições
Por padrão o Django vem com um sistema,
uma app, de controle de autenticação e
permissões:
django.contrib.auth
3. Algumas definições
O django.contrib.auth é uma app plugável que
já vem habilitada por padrão no arquivo de
configurações settings.py (na tupla de
installed_apps)
4. Algumas definições
Essa app, além de controlar a parte de login e
o acesso ao admin padrão do Django, também
permite atribuir permissões por Usuário e por Grupo
de Usuários as models das apps disponíveis no
admin (auth, sites e de suas apps que estão
habilitadas na tupla de installed_apps no arquivo
settings.py)
5. E como faz para testar ?
Para testar, acesse o admin com um usuário
com atributos de Membro da Equipe (is_staff) e com
Status de Super Usuário (is_superuser) e crie
um novo usuário.
Ob: Este novo usuário que você irá criar,
precisará ter o atributo Membro da Equipe (is_staff)
setado pois é isso que caracteriza a capacidade de se
logar no admin, mesmo que o Status de Super
Usuário esteja atribuido.
6. As permissões
Por padrão, o Django disponibiliza 3(três) tipos
de permissões padrões para o acesso a uma model:
- can_change (pode modificar/alterar objetos
daquela model.)
- can_add (pode adicionar objetos naquela model.)
- can_delete (pode deletar objetos daquela model.)
7. As permissões
Essas permissões podem ser atribuidas programaticamente, ou
através do admin, para isso, basta editar no admin o usuário e atribuir
as permissões em questão para a model específica.
Exemplo de atribuição de permissão programaticamente:
from minhaApp.models import MinhaModel
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
content_type = ContentType.objects.get_for_model(MinhaModel)
permission = Permission.objects.create(codename='can_change',
name='Can Change',
content_type=content_type)
8. As permissões
Ob: Também é possivel criar novas permissões
customizadas, setando uma tupla chamada permissions
em uma MetaClass de sua Model, por exemplo:
class MinhaModel(models.Model):
titulo = models.CharField(max_length=100)
class Meta:
permissions = (
("pode_ver", "Só pode ver"),
)
9. As permissões
Ao acessar o objeto em questão pode-se
verificar a existência da permissão:
if user.has_perm('minhaApp.pode_ver'):
# faz alguma coisa.
ou
if group.has_perm('minhaApp.pode_ver'):
# faz alguma coisa.
10. As permissões
As permissões também podem ser checadas
em funções(ou métodos) das views:
from django.contrib.auth.decorators import permission_required
@method_decorator(permission_required('minhaApp.pode_ver'))
def meu_metodo(self, *args, **kwargs):
# faz alguma coisa
11. As permissões
E também no template:
{% if perms.minhaApp.pode_ver %}
<div>
Conteúdo que eu posso ver
</div>
{% endif %}
12. As permissões
E quando o django sabe que existe estas permissões ?, quando ele
carrega elas ? O segredo está no middleware da app
django.contrib.auth
Este middleware está declarado no settings.py na tupla de
MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = (
.....
'django.contrib.auth.middleware.AuthenticationMiddleware',
.....
)
13. As permissões
Ao excutar este middleware o Django carrega todos os backends de permissão, que
estiverem registrados na variável AUTHENTICATION_BACKENDS (que é uma tupla
com o path completo para as classes que implementam os backends de permissão.)
Esta variável está localizada no global_settings.py da instalação do django
contendo o valor padrão ('django.contrib.auth.backends.ModelBackend',). E é aqui
neste backend que a mágica de carregar as permissões acontece.
Esta variável poderá ser redefinida no settings.py do projeto no caso de você
querer utilizar por exemplo o django-guardian (uma app que possibilita a configuração
de permissões por instâncias de objetos e não somente por Models) mas o djangoguardian é assunto para a próxima conversa.