Como Redesenhar o Django Admin com Bootstrap

O site de administração do Django é excelente — completo, fácil de usar, seguro por design, imbatível… e um tanto feio, o que pode ser um problema quando você deseja integrá-lo com o visual e a sensação do resto do seu site. Vamos resolver isso.

Se Não Está Quebrado…

The default Django admin. (Source)

Digamos que você acabou de prototipar um aplicativo web com Django e Vue.js. Para uma ampla gama de casos, usar o admin do Django para fins de back office tal como está, e até mesmo entregá-lo ao seu cliente após configurar permissões adequadamente, é perfeitamente bom. Afinal, funciona perfeitamente bem e pode ser altamente personalizado com as ferramentas internas para cobrir muitas situações.

Então, novamente, por que se preocupar?

Razões para Intervir no Visual e Sensação do Admin

No entanto, há várias razões válidas para dar um passo adiante na integração:

  • Branding: não há nada de errado em querer o nome e as cores da sua empresa em vez de “Administração do Django” (e, para constar, isso está em conformidade com a licença BSD do Django).
  • Integração perfeita entre o site principal e o admin: você pode querer alternar entre a funcionalidade de back office enquanto navega pelo site, e vice-versa, mantendo uma barra de navegação comum.
  • Embellecimento: embora o admin pareça bom e até tenha implementado princípios de design responsivo desde a versão 2 (funciona bem tanto em dispositivos móveis quanto em desktops), há muito que uma folha de estilo bem elaborada pode fazer para melhorar a aparência.
  • Funcionalidade de bypass: você também pode querer criar menus suspensos personalizados para o admin, exibindo as opções que realmente usa e ocultando do interface do usuário o que não precisa, o que poderia resultar em uma melhor experiência do usuário.

A Practical Example

Para este exemplo, e para não nos repetirmos, retomaremos a simples aplicação web de publicação que começamos para o artigo Prototipando uma Aplicação Web com Django e Vue.js.

Resumindo:

  • a Django app with two models:
  • Artigo com campos nome, autor (vinculado), conteúdo e slug
  • Autor: com campos nome e slug
  • A single view called frontend that queries all registries in both models.
  • A single template called template.
  • Implementação de Vue.js com Vue Router e Vuex para uma interface reativa escalável.

Não nos preocuparemos particularmente com a integração do Vue.js neste artigo, e não o modificaremos aqui.

O Template Básico

Source

Templates Django são muito versáteis e poderosos, e podem ser criados no nível do app (um componente do site Django) ou no nível do site, e podem até mesmo substituir os templates que vêm com o Django (o que faremos aqui).

Source

Criamos um template básico que vincula ao Bootstrap seu JavaScript e folha de estilo, e também suas ferramentas complementares, jQuery e Popper.

Aqui está o template base que estamos usando para o site principal, nada diferente do que normalmente usamos para qualquer outro site Django:

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

    <title>Django and Vue.js</title>
  </head>
  <body class="bg-light">
    <div class="bg-white container">
      <h1>Prototyping a Web App with Django and Vue.js</h1>

      <!-- Content -->
    </div>

    <!-- Vue.js -->
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/vue-router"></script>

    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
  </body>
</html>

Em seguida, vamos integrar isso no admin, e adicionar uma barra de navegação compartilhada em ambos os lados — o site principal e o back office!

Integrando o Template de Interface do Usuário Principal com o Admin

Como mencionado, podemos sobrescrever templates, incluindo os do admin. No entanto, devido ao design do Django, e sem surpresa, o site principal e o back office são dois sistemas diferentes, cada um com seus próprios templates, folhas de estilo e contrib packages. Portanto, mesmo que eles sejam quase idênticos, precisaremos manter dois templates diferentes — um para a interface principal do usuário e um para o admin.

Habilitando um Diretório para Templates em Geral

Primeiro, precisamos informar ao Django onde armazenaremos o template modificado do admin no diretório base.

Então, precisaremos editar myproject/settings.py. Primeiro, encontre a constante TEMPLATES e esta chave DIRS:

'DIRS': [],

Mude esse código para isto:

'DIRS': [os.path.join(BASE_DIR, 'templates')],

Envolvendo o Template do Admin (admin/base Hack)

Se apenas quiséssemos fazer alterações cosméticas, como passar uma folha de estilo personalizada para o admin, ou remover/substituir seu cabeçalho, poderíamos fazer isso editando o template admin/base_site e pulando completamente esta etapa atual. No entanto, se quisermos ir até o fim e “envolver” a seção do admin como se estivesse contida dentro de nosso site principal, com a possibilidade de ter um cabeçalho e rodapé comuns, continue lendo.

Precisaremos copiar o admin/base.html do Django para nosso diretório de templates em templates/admin/base.html, para que possamos colocar nossos envolvimentos.

Vamos editar o código em torno da seção container, de modo que passe de:

<!-- Container -->
<div id="container">
(...)
</div>
<!-- END Container -->

para isto:

{% block bodyheader %}{% endblock %}

<!-- Container -->
<div id="container">
(...)
</div>
<!-- END Container -->

{% block bodyfooter %}{% endblock %}

E pronto! Simplesmente criamos tags de bloco bodyheader e bodyfooter, para que pudéssemos injetar o código que envolverá o admin na próxima etapa.

Codificando um Template de Admin Personalizado (admin/base_site Hack)

Então, vamos codificar o template real em templates/admin/base_site.html (precisaremos criar os diretórios na raiz do nosso projeto):

{% extends "admin/base_site.html" %}

{% block title %}Django with Bootstrap | Admin site{% endblock %}

{% block branding %}{% endblock %}
{% block breadcrumbs %}{% endblock %}

{% block bodyclass %}bg-light{% endblock %}

{% block extrastyle %}
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <style>
      #header, .breadcrumbs { display: none; }

      /* Problemas do Bootstrap com o admin */
      * { box-sizing: unset; }
      div.module caption { caption-side: top !important; }
      .collapse { display: block !important; }
    </style>
{% endblock %}

{% block bodyheader %}
    <div class="bg-white container">

      <div class="jumbotron">
        <h1 class="display-4">Hacking the Django Admin with Bootstrap</h1>
        <p class="lead">
          The <a ref="https://docs.djangoproject.com/en/dev/ref/contrib/admin/">Django administration site</a> is great—full-featured, easy to use, secure by design, rock solid… and somewhat ugly, which can be something of a downside when you want to integrate it with the look-and-feel of the rest of the website. Let’s sort that out.
        </p>
      </div>
{% endblock %}

{% block bodyfooter %}
    </div>

    <!-- jQuery primeiro, depois Popper.js, depois Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
{% endblock %}

Análise

Vamos tentar explicar o que estamos fazendo aqui:

  1. Dizemos ao mecanismo do template que estamos “estendendo” o template admin/base_site.html, para substituir efetivamente algumas de suas definições.
  2. Utilizamos o bloco title para personalizar um título para a página de administração sendo navegada.
  3. Vazamos o conteúdo dos blocos branding e breadcrumbs, pois não os precisamos realmente.
  4. Usamos o bloco bodyclass para definir o bg-light do Bootstrap, como fizemos no template frontend.
  5. Utilizamos o bloco extrastyle para incorporar o Bootstrap e algum código CSS.
    a. Ok, #header, .breadcrumbs { display: none; } é uma espécie de reafirmação do número 3; mas é útil saber que você pode desabilitar as seções de branding e breadcrumbs de ambas as maneiras.
    b. Pode haver alguns problemas ao sobrepor o Bootstrap com o CSS do Django no admin, então estas são algumas correções.
  6. Use os blocos bodyheader e bodyfooter para envolver o conteúdo do admin.

Agora que temos acesso ao template do admin, poderíamos expandir sua folha de estilo, ou simplesmente deixá-lo assim com um estilo compartilhado com a UI principal.

Avisos

Estamos mantendo dois templates diferentes (principal e de administração) para fazer essencialmente a mesma apresentação. Admitidamente, isso não é ideal, pois estamos explicitamente violando um dos princípios fundamentais do desenvolvimento de software: não se repita (DRY).

Como comentamos, isso ocorre porque o admin do Django foi projetado para ser independente da interface principal. E não há nada de errado com isso, assim como não há nada de errado em pensar fora da caixa. Mas sim, isso nos obriga a usar dois templates com quase o mesmo conteúdo.

Na verdade, em princípio poderíamos projetar um padrão de template que incluísse aquele navbar e outros elementos comuns da interface principal e do admin, e reutilizá-los a partir desse único ponto de origem; mas neste momento, e para o propósito deste artigo, essa abordagem seria um pouco exagerada. De qualquer forma, vou deixar a ideia plantada para você. 😉

Criando um Barra de Navegação Compartilhada

Agora que a interface principal e o site de administração são quase idênticos, podemos ir além na nossa integração e criar uma experiência de navegação comum… e ainda mais, apresentar algumas opções de administração diretamente no menu principal!

Aqui está o trecho para o navbar:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <ul class="navbar-nav mr-auto">
    <li class="nav-item">
      <a
        class="nav-link text-primary"
        href="/author/"
      >
        Go to Authors
      </a>
    </li>
    <li class="nav-item">
      <a
        class="nav-link text-primary"
        href="/article/"
      >
        Go to Articles
      </a>
    </li>
    {% if user.is_authenticated %}
    <li class="nav-item dropdown">
      <a
        aria-expanded="false"
        aria-haspopup="true"
        class="font-weight-bold nav-link text-primary dropdown-toggle"
        data-toggle="dropdown"
        href="#"
        role="button"
      >
        Admin
      </a>
      <div class="dropdown-menu">
        <a class="dropdown-item" href="/admin/myapp/author/">
          Manage authors
        </a>
        <a class="dropdown-item" href="/admin/myapp/article/">
          Manage articles
        </a>
      </div>
    </li>
    {% endif %}
  </ul>
</nav>

Observe a seção dropdown-menu, que cuidará de apresentar um menu de administração (consulte o componente Navbar do Bootstrap para mais informações).

Também realizamos uma verificação condicional com {% if user.is_authenticated %} /{% endif %}, para decidir se mostramos ou não o menu do administrador.

Por fim, lembre-se de que, já que agora estamos mantendo dois modelos principais diferentes, precisaremos adicionar o código HTML do navbar a ambos, myapp/templates/myapp/template.html e templates/admin/base_site.html.

Extra: Tela de Login do Admin

O site do administrador foi cuidado, mas ainda há um fio solto: a tela de login.

Agora poderíamos transformar algo como isto:

Source

… em algo como isto:

Podemos alcançar algo mais próximo disso criando o seguinte modelo em templates/admin/login.html:

{% extends "admin/login.html" %}

{% load i18n static %}

{% block extrastyle %}
{{ block.super }}
<style>
#header {
  background-color: transparent !important;
}
</style>
{% endblock %}

{% block branding %}
<h1>
  <span style="color: #57C5A5 !important">ActionPlanNow.com</span>
  <br />
  <small>{% block head_title %}{% endblock %}</small>
</h1>
{% endblock %}

{% block content_title %}
<p class="lead" style="font-size: larger">
A Simple Tool for Leaders, Coaches, and Counselors.
</p>
{% endblock %}

Análise

O que estamos fazendo aqui:

  1. A tag {{ block.super }} está lá para dizer ao mecanismo de templates que não estamos substituindo o conteúdo de extrastyle (que definimos no modelo templates/admin/base_site.html), mas que estamos simplesmente adicionando conteúdo a ele (veja herança de templates para mais informações).
  2. O bloco branding nos permite alterar o cabeçalho “Administração Django” para algo mais interessante.
  3. Nós nos livramos do bloco head_title definindo uma definição vazia.
  4. Utilizamos o bloco content_title para adicionar algumas informações extras.

Algumas Considerações

Source

Assim como Bootstrap, o site de administração do Django também vem com seu próprio conjunto de jQuery, mas felizmente os desenvolvedores do Django pensaram nisso e, para evitar conflitos com scripts e bibliotecas fornecidas pelo usuário, o jQuery do Django é namespaced como django.jQuery. Assim, podemos incluir nossa própria cópia (como fizemos) com segurança.

Tenha cuidado ao se exagerar com definições de classe em seu arquivo de estilo principal, pois isso também afetará o site de administração, afetando sua funcionalidade de maneiras inesperadas. Nesse caso, você sempre pode ver o que está acontecendo com as ferramentas de depuração do navegador, como Chrome DevTools, Firefox Developer Tools (particularmente Page Inspector) ou Safari Developer Tools.

Demonstração e Código Completo

Esta implementação que discutimos aqui se parecerá com isto:

Você pode navegar por todo o código do projeto no meu repositório do GitHub, luzdealba / djangovuejs.

Conclusão

Embora alguns possam afirmar, com boa razão, que não há muita necessidade de alterar a aparência do admin do Django, também é verdade que integrar suavemente os diferentes endpoints de um site é uma boa solução para melhorar a UX, pois pode proporcionar uma transição perfeita entre os dois, e até uma navegação mais controlada no admin.

E fazer isso não é tão difícil. O que você precisa prestar atenção é como você envolve o admin, e também como mescla bibliotecas de terceiros com seu próprio código JavaScript e folhas de estilo. Felizmente, você pode facilmente integrar algumas no admin, algumas no restante do site principal e algumas em ambos.

Espero que você tenha algumas ideias sobre como pode personalizar ainda mais o Django de maneiras que não eram tão evidentes!

Se precisar de um pretexto para criar um aplicativo web apenas para brincar com o admin do Django, confira o tutorial da semana passada sobre prototipagem de um aplicativo web com Django e Vue.js — é muito divertido. E se você deseja aprofundar suas habilidades com Django, a Biblioteca Premium do SitePoint tem muitos recursos para você.

Perguntas Frequentes (FAQs) sobre Personalização do Django Admin com Bootstrap

Quais são os benefícios de personalizar o Django Admin com Bootstrap?

Personalizar o Django Admin com Bootstrap oferece várias vantagens. Primeiro, ele melhora o apelo visual de sua interface administrativa, tornando-a mais amigável e intuitiva. Bootstrap é um framework front-end popular que fornece uma variedade de modelos de design para tipografia, formulários, botões e outros componentes da interface. Integrando-o com o Django Admin, você pode aproveitar esses modelos para criar uma interface administrativa mais atraente e funcional. Em segundo lugar, permite adicionar funcionalidades personalizadas à sua interface administrativa. Por exemplo, você pode adicionar ações personalizadas, filtros e formulários para melhorar a usabilidade de sua interface administrativa. Por último, pode melhorar a responsividade de sua interface administrativa, tornando-a mais acessível em diferentes dispositivos e tamanhos de tela.

Como posso adicionar ações personalizadas ao Django Admin?

O Django Admin permite adicionar ações personalizadas que podem ser executadas em objetos selecionados. Para adicionar uma ação personalizada, você precisa definir uma função que execute a ação desejada nos objetos selecionados. Essa função deve receber três parâmetros: o administrador do modelo, a solicitação e um queryset dos objetos selecionados. Depois de definir essa função, você pode adicioná-la ao atributo ‘ações’ do seu administrador de modelo. Isso fará com que a ação fique disponível na lista suspensa de ações na página de alteração da lista administrativa.

Posso personalizar a aparência e o estilo do Django Admin usando Bootstrap?

Sim, você pode personalizar a aparência e o estilo do Django Admin usando Bootstrap. Bootstrap é uma estrutura front-end que fornece uma variedade de modelos de design para tipografia, formulários, botões e outros componentes de interface. Integrando-o com o Django Admin, você pode aproveitar esses modelos para criar uma interface administrativa mais visualmente atraente e funcional. Você pode personalizar cores, fontes, layout e outros elementos de design da sua interface administrativa para combinar com a identidade da sua marca ou preferências pessoais.

Como posso adicionar filtros personalizados ao Django Admin?

O Django Admin permite adicionar filtros personalizados que podem ser usados para filtrar os objetos exibidos na página de lista de alterações do administrador. Para adicionar um filtro personalizado, você precisa definir uma subclasse de django.contrib.admin.SimpleListFilter. Essa subclasse deve definir dois métodos: lookups e queryset. O método lookups deve retornar uma lista de tuplas, cada uma representando uma opção de filtro. O método queryset deve retornar um queryset filtrado com base na opção de filtro selecionada. Depois de definir essa subclasse, você pode adicioná-la ao atributo ‘list_filter’ de seu administrador de modelo.

Posso usar Bootstrap com Django Admin sem nenhum pacote adicional?

Embora seja possível usar Bootstrap com Django Admin sem nenhum pacote adicional, geralmente é mais fácil e eficiente usar um pacote como django-admin-bootstrap. Este pacote fornece um tema baseado em Bootstrap para o Django Admin, facilitando a integração de Bootstrap com o Django Admin. Ele também fornece recursos adicionais como design responsivo e renderização de formulários personalizados, o que pode melhorar ainda mais a usabilidade e a funcionalidade da sua interface administrativa.

Como posso personalizar os campos do formulário no Django Admin?

O Django Admin permite que você personalize os campos do formulário usados para criar ou editar objetos. Para personalizar um campo de formulário, você precisa sobrescrever o método ‘formfield_for_dbfield’ do seu admin de modelo. Este método deve retornar uma instância de campo de formulário que será usada para o campo de banco de dados especificado. Você pode personalizar os atributos, widgets e comportamento de validação do campo de formulário para atender às suas necessidades.

Posso adicionar visualizações personalizadas ao Django Admin?

Sim, você pode adicionar visualizações personalizadas ao Django Admin. Para adicionar uma visualização personalizada, você precisa definir um método em seu admin de modelo que lide com a lógica da visualização. Este método deve receber um pedido como seu único parâmetro e retornar uma resposta. Em seguida, você pode mapear este método para uma URL adicionando um padrão de URL ao método ‘get_urls’ do seu admin de modelo. Isso tornará a visualização acessível a partir da interface do administrador.

Como posso personalizar a exibição da lista no Django Admin?

O Django Admin permite que você personalize a exibição da lista, que é a tabela de objetos exibida na página de lista de alterações do administrador. Para personalizar a exibição da lista, você pode definir o atributo ‘list_display’ do seu admin de modelo como uma lista de nomes de campos que deseja exibir. Você também pode incluir nomes de métodos nesta lista, que chamarão o método correspondente em cada objeto e exibirão o resultado.

Posso usar o Django Admin para modelos de banco de dados complexos?

Sim, o Django Admin é projetado para lidar com modelos de banco de dados complexos. Ele oferece uma variedade de recursos que podem ajudá-lo a gerenciar estruturas de dados complexas, como edição inline de objetos relacionados, campos de formulário personalizados e ações personalizadas. No entanto, para estruturas de dados muito complexas ou operações de banco de dados avançadas, você pode precisar estender o Django Admin com views, formulários ou ações personalizados.

Como posso melhorar o desempenho do Django Admin?

Existem várias maneiras de melhorar o desempenho do Django Admin. Uma maneira é otimizar suas consultas ao banco de dados. O Django Admin gera automaticamente consultas ao banco de dados com base em suas definições de modelo e opções de administração. No entanto, essas consultas podem às vezes ser ineficientes, especialmente para estruturas de dados complexas ou grandes conjuntos de dados. Ao personalizar suas opções de administração e usar recursos de otimização de banco de dados do Django, você pode reduzir significativamente o número de consultas ao banco de dados e melhorar o desempenho de sua interface de administração. Outra maneira é usar cache. O Django fornece uma estrutura de cache robusta que você pode usar para cachear os resultados de operações caras ou dados acessados com frequência. Ao usar cache, você pode reduzir a carga no seu banco de dados e melhorar a responsividade de sua interface de administração.

Source:
https://www.sitepoint.com/how-to-hack-redesign-customize-the-django-admin-with-bootstrap/