Pular para o conteúdo
dicas de djangopor Regis do Python

Dica 31 - Django Admin: Pegando usuário logado no Admin

3 min de leitura
Assistir ao vídeo no YouTube: 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 no save_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 nela request.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: False quando o registro está sendo criado e True quando 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.

Sugerir uma correção nesta página