Dica 31 - Django Admin: Pegando usuário logado no Admin
Versões usadas no vídeo: Django 2.2.19 e Python 3.8.
Código: https://github.com/rg3915/dicas-de-django
Muitas vezes queremos registrar quem criou um registro: o autor de um artigo, o responsável por um pedido etc. Pelo Django Admin, o usuário que está logado está disponível em request.user, e o ModelAdmin tem um método, o save_model, que é chamado na hora de salvar. Nesta dica vamos sobrescrever o save_model para preencher automaticamente o usuário do artigo com o usuário logado.
Pré-requisitos
Continuamos o projeto das dicas anteriores do Admin (Dica 29 e Dica 30): um app core dentro de myproject, com o modelo Article e o ArticleAdmin.
O campo user no modelo
Em models.py, importe o User e acrescente ao Article uma chave estrangeira para ele:
# myproject/core/models.py
import uuid
from django.db import models
from autoslug import AutoSlugField
from hashid_field import HashidAutoField
from django.contrib.auth.models import User
# ... (veja o arquivo completo no GitHub)
class Article(models.Model):
# ... (veja o arquivo completo no GitHub)
status = models.CharField(max_length=1, choices=STATUS_CHOICES)
user = models.ForeignKey(
User,
on_delete=models.SET_NULL,
null=True,
blank=True
)
# ... (veja o arquivo completo no GitHub)
Código completo: myproject/core/models.py
on_delete=models.SET_NULL: se o usuário for apagado, o artigo continua existindo, só fica sem usuário.null=True, blank=True: o campo é opcional, tanto no banco quanto no formulário. Isso é importante, porque vamos deixar o campo vazio no formulário e preenchê-lo nosave_model.
Como mudamos o modelo, crie e aplique a migration:
python manage.py makemigrations
python manage.py migrate
No repositório, ela ficou assim:
# myproject/core/migrations/0006_article_user.py
# Generated by Django 2.2.19 on 2021-03-08 02:40
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('core', '0005_article_status'),
]
operations = [
migrations.AddField(
model_name='article',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
]
Sobrescrevendo o save_model no Admin
Em admin.py, dentro do ArticleAdmin, sobrescreva o método save_model:
def save_model(self, request, obj, form, change):
if not change:
obj.user = request.user
obj.save()
super(ArticleAdmin, self).save_model(request, obj, form, change)
O Admin chama save_model(request, obj, form, change) toda vez que você clica em salvar na tela de adicionar ou de editar:
request: a requisição, e nelarequest.user, o usuário logado no Admin.obj: a instância do modelo (o artigo) que vai ser salva.form: o formulário do Admin, já validado.change:Falsequando o registro está sendo criado eTruequando está sendo editado.
Com if not change, o usuário só é preenchido na criação do artigo. Se outro usuário editar o artigo depois, o autor original continua o mesmo. No fim, chamamos o save_model da classe pai (super), que é quem salva o objeto de fato (obj.save()).
O trecho principal do admin.py (o arquivo completo está no link logo abaixo):
# myproject/core/admin.py
# ... (veja o arquivo completo no GitHub)
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
# ... (veja o arquivo completo no GitHub)
def save_model(self, request, obj, form, change):
if not change:
obj.user = request.user
obj.save()
super(ArticleAdmin, self).save_model(request, obj, form, change)
# ... (veja o arquivo completo no GitHub)
Código completo: myproject/core/admin.py
Testando
Rode o servidor, entre no Admin e clique em Add artigo. O formulário agora tem o campo User. Deixe esse campo vazio, preencha os outros (no vídeo, título "Novo", categoria Python e status Retirado) e salve.
Abra o artigo recém-criado: o campo User está preenchido com admin, o usuário que estava logado no momento em que o artigo foi criado.
Conclusão
O save_model é o lugar certo no Admin para mexer no objeto antes de salvar usando dados da requisição, e o request.user dá o usuário logado. Com o if not change, o usuário é gravado só na criação do registro.
Observação: o vídeo importa User direto de django.contrib.auth.models. Em projetos com usuário personalizado, o recomendado é usar settings.AUTH_USER_MODEL no ForeignKey.