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)