DEV Community

Cover image for django-admin: criando um AdminSite customizado sem perder o registro automático dos Models
Eduardo Oliveira
Eduardo Oliveira

Posted on

django-admin: criando um AdminSite customizado sem perder o registro automático dos Models

Ao trabalhar com django, principalmente utilizando o django-admin, é bastante comum não nos preocuparmos, sempre, com os models que são registrados ao painel de admin padrão.

O motivo disso é bem simples: na maioria dos casos não precisamos tocar na instância padrão da classe AdminSite, que é a classe que define como o painel admin irá ser exibido.

Quando não precisamos trocar a instância do AdminSite que utilizamos, o registro automático dos models sempre nos satisfaz.

Porém, ao surgir a necessidade de sobrescrever o AdminSite padrão, costumamos perder o registro automático dos models feitos pelos diversos pacotes (libs, bibliotecas, etc.) que instalamos no nosso projeto.

Motivação

A motivação pra se lidar com esse problema, é que em algumas situações precisamos alterar o AdminSite padrão. Um exemplo clássico e que costuma surgir bastante é: quando é preciso ordenar os Apps e os Models na página inicial do nosso admin.

O AdminSite Padrão

Quando executamos o comando abaixo, para iniciar um novo projeto (existem outras variações do comando, não se preocupe), por padrão, teremos o arquivo core/urls.py do código a seguir

django-admin startproject core .
Enter fullscreen mode Exit fullscreen mode
# core/urls.py
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]
Enter fullscreen mode Exit fullscreen mode

Nesse arquivo, é registrada uma instância padrão do AdminSite que, por sua vez, é importada do caminho: django.contrib.admin.site.

Com o projeto em execução (python manage.py runserver), ao realizar login no painel de admin, teremos a seguinte tela:

tela inicial do django-admin

Alterando o AdminSite

Para alterar o AdminSite é bem simples, criando um arquivo core/site.py:

# core/site.py
from django.contrib.admin import AdminSite

class CustomSite(AdminSite):
    pass

site = CustomSite()
Enter fullscreen mode Exit fullscreen mode

E alterando, então, o core/urls.py:

# core/urls.py
from django.urls import path
from .site import site

urlpatterns = [
    path('admin/', site.urls),
]
Enter fullscreen mode Exit fullscreen mode

A tela inicial do admin nesse momento, assume uma outra estética, sem permissão pra visualizar ou editar nada (pois não há nenhum model registrado):

página inicial do admin do django sem models

AdminSite Padrão

No exemplo acima, substituímos o import do admin.site original pelo .site.admin. Podemos alterar, porém, esse código para substituir o AdminSite padrão do projeto e, dessa forma, não perderemos os models registrados automáticamente:

# core/site.py
from django.contrib.admin import AdminSite

class CustomSite(AdminSite):
    def get_app_list(self, request):
        """
        Return a sorted list of all the installed apps that have been
        registered in this site.
        """
        app_dict = self._build_app_dict(request)

        # Sort the apps alphabetically.
        app_list = sorted(app_dict.values(), key=lambda x: x['name'].lower())

        # Sort the models alphabetically within each app.
        for app in app_list:
            app['models'].sort(key=lambda x: x['name'])
            app['models'].reverse()

        return app_list
Enter fullscreen mode Exit fullscreen mode

Foi adicionado, aqui, um código apenas para alterar a ordem dos models dentro dos apps para que possamos ver efeitos visuais na tela (Referência do código aqui). Além disso, foi removida aquela chamada site = CustomSite().

A partir de agora, é preciso reverter o core/urls.py:

# core/urls.py
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]
Enter fullscreen mode Exit fullscreen mode

Além desses dois passos, é preciso criar um core/apps.py onde será criada uma instância da classe AdminConfig definindo quem é o AdminSite padrão:

# core/apps.py
from django.contrib.admin.apps import AdminConfig

class MyAdminConfig(AdminConfig):
    default_site = 'core.site.CustomSite'
Enter fullscreen mode Exit fullscreen mode

Por último, no settings.py:

# core/settings.py

# ...

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

# ...
Enter fullscreen mode Exit fullscreen mode

É preciso substituir o django.contrib.admin pelo core.apps.MyAdminConfig:

# core/settings.py

# ...

INSTALLED_APPS = [
    'core.apps.MyAdminConfig',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

# ...
Enter fullscreen mode Exit fullscreen mode

Resultados

Quando entramos na página inicial do admin agora, temos a seguinte exibição:

django-admin

Quando alteramos o código comentando a seguinte linha, passamos a ter outro resultado:

# app['models'].reverse()
Enter fullscreen mode Exit fullscreen mode

django-admin

O código fonte final desse texto está disponível no GitHub.

Referências

Top comments (0)