Como substituir e estender os modelos básicos de administração do Django?


125

Como substituir um modelo de administrador (por exemplo, admin / index.html) e ao mesmo tempo estendê-lo (consulte https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing -um-admin-template )?

Primeiro - eu sei que essa pergunta já foi feita e respondida antes (consulte Django: Substituindo E estendendo um modelo de aplicativo ), mas como a resposta diz que não é diretamente aplicável se você estiver usando o carregador de modelos app_directories (que é a maioria dos Tempo).

Minha solução atual é fazer cópias e estender a partir delas, em vez de estender diretamente dos modelos de administrador. Isso funciona muito bem, mas é realmente confuso e adiciona trabalho extra quando os modelos de administrador são alterados.

Poderia pensar em uma tag de extensão personalizada para os modelos, mas não quero reinventar a roda se já existir uma solução.

Em uma nota lateral: Alguém sabe se este problema será resolvido pelo próprio Django?


1
Copiar os modelos de administração, estendê-los e substituir / adicionar blocos é o fluxo de trabalho mais eficiente, embora não ideal, considerando o estado atual do Django. Eu não vi qualquer outra maneira de fazer o que você está tentando fazer em três anos de trabalho com ele :)
— Brandon

Bem - não sei se isso é bom ou não, mas pelo menos pessoas como você chegaram à mesma conclusão. É bom ouvir isso. :)
— Semmel

Respostas:


101

Atualização :

Leia o Docs para sua versão do Django. por exemplo

https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#admin-overriding-templates https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#admin-overriding -modelos

Resposta original de 2011:

Eu tive o mesmo problema há cerca de um ano e meio e encontrei um bom carregador de modelos no djangosnippets.org que facilita isso. Ele permite que você estenda um modelo em um aplicativo específico, permitindo que você crie seu próprio admin / index.html que estende o modelo admin / index.html do aplicativo de administração. Como isso:

{% extends "admin:admin/index.html" %}

{% block sidebar %}
    {{block.super}}
    <div>
        <h1>Extra links</h1>
        <a href="https://stackoverflow.com/admin/extra/">My extra link</a>
    </div>
{% endblock %}

Eu dei um exemplo completo de como usar esse carregador de modelos em uma postagem do blog no meu site.


18
Para referência; o fragmento em questão tenha sido convertido para uma aplicação Django, e está disponível em PyPI (pip / easy_install) como django-apptemplates: pypi.python.org/pypi/django-apptemplates
— Romløk

9
Apenas para ser 100% explícito: a solução acima não funcionará mais nas versões recentes do Django (pelo menos 1.4), pois uma das funções que o script usa é depreciada. Você pode encontrar a fonte atualizada aqui
— OldTinfoil

2
Note que com o Django 1.8 isso ainda funcionará, mas a configuração precisa ser feita de uma maneira especial (veja app_namespace.Loader setup como um exemplo). O django-app-namespace-template-loader também é uma alternativa funcional para django-apptemplatesse ele parar de funcionar um dia.
— Peterino 11/11/15

Esta resposta foi muito boa para as versões mais antigas do Django. Mas, a partir de agora, outra resposta de Cheng é mais relevante. stackoverflow.com/a/29997719/7344164
— SoftwareEnggUmar

70

Quanto ao Django 1.8 ser a versão atual, não há necessidade de ligar novamente, copiar o admin / templates para a pasta do projeto ou instalar middlewares, conforme sugerido pelas respostas acima. Aqui está o que fazer:

  1. crie a seguinte estrutura em árvore (recomendada pela documentação oficial )

    your_project
         |-- your_project/
         |-- myapp/
         |-- templates/
              |-- admin/
                  |-- myapp/
                      |-- change_form.html  <- do not misspell this

Nota : A localização deste arquivo não é importante. Você pode colocá-lo dentro do seu aplicativo e ele ainda funcionará. Desde que sua localização possa ser descoberta pelo django. O que é mais importante é que o nome do arquivo HTML deve ser o mesmo que o nome original do arquivo HTML fornecido pelo django.

  1. Adicione este caminho de modelo às suas configurações.py :

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')], # <- add this line
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
  2. Identifique o nome e o bloco que você deseja substituir. Isso é feito olhando para o diretório admin / templates do django. Estou usando o virtualenv, então, para mim, o caminho está aqui:

    ~/.virtualenvs/edge/lib/python2.7/site-packages/django/contrib/admin/templates/admin

Neste exemplo, desejo modificar o formulário Adicionar novo usuário. O modelo responsável por esta visualização é change_form.html . Abra o change_form.html e localize o {% block%} que deseja estender.

  1. Em seu change_form.html , escreva algo assim:

    {% extends "admin/change_form.html" %}
    {% block field_sets %}
         {# your modification here #}
    {% endblock %}
  2. Carregue sua página e você verá as alterações


Ainda não é suficiente para estender o modelo principal "index.html", sem copiar todos os blocos. Uma solução é escrever alguns ../para "expandir" o caminho e especificar o caminho original mais exclusivo {% extends "../../admin/templates/admin/index.html" %}. link para resposta
— hynekcer 15/06

1
Eu acho que em TEMPLATES devemos usar 'DIRS': [os.path.join (BASE_DIR, 'templates')],
— Raul Reyes

Esse é o tipo de thread que ilustra perfeitamente a falha no SO. Uma estrutura é atualizada e a pergunta não é mais relevante, é de fato um impedimento do caminho adequado. Ótima resposta aqui. Crianças RTFM.
— Derek Adair

Obrigado por esta resposta. Exceto por "O local deste arquivo não é importante.", Tudo funcionou bem.
— Jaswanth Manigundan

54

se você precisar sobrescrever o admin/index.html, poderá definir o parâmetro index_template do AdminSite.

por exemplo

# urls.py
...
from django.contrib import admin

admin.site.index_template = 'admin/my_custom_index.html'
admin.autodiscover()

e coloque seu modelo em <appname>/templates/admin/my_custom_index.html


5
Brilhante! Isso permite que você faça {% extends "admin/index.html" %}my_custom_index.html e faça referência ao modelo de administração do django sem copiá-lo. Obrigado.
— Mattmc3

3
O @Semmel deve marcar isso como a resposta correta, já que é a abordagem mais simples que usa recursos internos do django e não requer o uso de carregadores de modelos personalizados.
— MrColes


9

A resposta de Chengs está correta, mas, de acordo com os documentos do administrador, nem todos os modelos de administrador podem ser substituídos da seguinte maneira: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#overriding-admin-templates

Modelos que podem ser substituídos por aplicativo ou modelo

Nem todo modelo em contrib / admin / templates / admin pode ser substituído por aplicativo ou por modelo. O seguinte pode:

app_index.html
change_form.html
change_list.html
delete_confirmation.html
object_history.html

Para os modelos que não podem ser substituídos dessa maneira, você ainda pode substituí-los por todo o projeto. Basta colocar a nova versão no diretório templates / admin . Isso é particularmente útil para criar páginas 404 e 500 personalizadas

Eu tive que sobrescrever o login.html do administrador e, portanto, tive que colocar o modelo sobrescrito nessa estrutura de pastas:

your_project
 |-- your_project/
 |-- myapp/
 |-- templates/
      |-- admin/
          |-- login.html  <- do not misspell this

(sem a subpasta myapp no ​​admin) Não tenho repugnância suficiente para comentar sobre o post de Cheng, por isso tive que escrever isso como nova resposta.


Obrigado pelo feedback hyneker. Espero que minha resposta seja mais clara e mais direta agora.
— Matyas

Sim, é útil saber que os modelos podem ser personalizados no nível do projeto, mesmo que alguns deles possam ser alterados opcionalmente no nível do aplicativo.
— Hynekcer

5

A melhor maneira de fazer isso é colocar os modelos de administração do Django dentro do seu projeto. Portanto, seus modelos estariam dentro templates/admindos modelos de administração do Django template/django_admin. Em seguida, você pode fazer algo como o seguinte:

templates / admin / change_form.html

{% extends 'django_admin/change_form.html' %}

Your stuff here

Se você está preocupado em manter os modelos de ações atualizados, pode incluí-los com svn externals ou similar.


Usar svn externals é uma ótima idéia. O problema que isso apresenta é que todos os meus tradutores traduzirão todos esses modelos (porque o makemages coletará as strings de tradução de todos os modelos de administração), o que adiciona muito trabalho extra se você estiver trabalhando com vários idiomas. Talvez haja uma maneira de excluir esses modelos de makemessages?
— Semmel

Use o --ignoreargumento com makemessages. Veja: docs.djangoproject.com/en/dev/ref/django-admin/#makemessages
— Chris Pratt

Acho que a outra resposta se encaixa melhor na minha necessidade. Mas gosto da sua solução e acho que é uma boa alternativa se você não quiser mexer com os carregadores de modelos.
— Semmel

5

Não consegui encontrar uma única resposta ou uma seção nos documentos oficiais do Django que tinham todas as informações necessárias para substituir / estender os modelos de administrador padrão. Por isso, estou escrevendo essa resposta como um guia completo, esperando que seja útil para outros no futuro.

Assumindo a estrutura padrão do projeto Django:

mysite-container/         # project container directory
    manage.py
    mysite/               # project package
        __init__.py
        admin.py
        apps.py
        settings.py
        urls.py
        wsgi.py
    app1/
    app2/
    ...
    static/
    templates/

Aqui está o que você precisa fazer:

  1. Em mysite/admin.py, crie uma subclasse de AdminSite:

    from django.contrib.admin import AdminSite
    
    
    class CustomAdminSite(AdminSite):
        # set values for `site_header`, `site_title`, `index_title` etc.
        site_header = 'Custom Admin Site'
        ...
    
        # extend / override admin views, such as `index()`
        def index(self, request, extra_context=None):
            extra_context = extra_context or {}
    
            # do whatever you want to do and save the values in `extra_context`
            extra_context['world'] = 'Earth'
    
            return super(CustomAdminSite, self).index(request, extra_context)
    
    
    custom_admin_site = CustomAdminSite()

    Certifique-se de importar custom_admin_siteos admin.pyaplicativos e registrar seus modelos nele para exibi-los em seu site de administração personalizado (se desejar).

  2. Em mysite/apps.py, crie uma subclasse de AdminConfige defina default_sitepara admin.CustomAdminSitea etapa anterior:

    from django.contrib.admin.apps import AdminConfig
    
    
    class CustomAdminConfig(AdminConfig):
        default_site = 'admin.CustomAdminSite'
  3. Em mysite/settings.py, substituir django.admin.siteem INSTALLED_APPScom apps.CustomAdminConfig(o administrador personalizado aplicativo de configuração da etapa anterior).

  4. Em mysite/urls.py, substitua admin.site.urlsdo URL do administrador paracustom_admin_site.urls

    from .admin import custom_admin_site
    
    
    urlpatterns = [
        ...
        path('admin/', custom_admin_site.urls),
        # for Django 1.x versions: url(r'^admin/', include(custom_admin_site.urls)),
        ...
    ]
  5. Crie o modelo que você deseja modificar em seu templatesdiretório, mantendo a estrutura de diretório padrão dos modelos de administração do Django, conforme especificado nos documentos . Por exemplo, se você estava modificando admin/index.html, crie o arquivotemplates/admin/index.html .

    Todos os modelos existentes podem ser modificados dessa maneira, e seus nomes e estruturas podem ser encontrados no código fonte do Django .

  6. Agora você pode substituir o modelo escrevendo-o do zero ou estendendo-o e, em seguida, substituindo / estendendo blocos específicos.

    Por exemplo, se você deseja manter tudo como está, mas deseja substituir o contentbloco (que na página de índice lista os aplicativos e seus modelos registrados), adicione o seguinte a templates/admin/index.html:

    {% extends 'admin/index.html' %}
    
    {% block content %}
      <h1>
        Hello, {{ world }}!
      </h1>
    {% endblock %}

    Para preservar o conteúdo original de um bloco, adicione {{ block.super }}onde quiser que o conteúdo original seja exibido:

    {% extends 'admin/index.html' %}
    
    {% block content %}
      <h1>
        Hello, {{ world }}!
      </h1>
      {{ block.super }}
    {% endblock %}

    Você também pode adicionar estilos e scripts personalizados, modificando os blocos extrastylee extrahead.


você tem uma fonte ou documentação sobre isso?
— Mary

Além das duas referências que adicionei no ponto 5, não, não tenho mais nada.
— Faheel

1

Eu concordo com Chris Pratt. Mas acho que é melhor criar o link simbólico para a pasta original do Django, onde os modelos de administração estão:

ln -s /usr/local/lib/python2.7/dist-packages/django/contrib/admin/templates/admin/ templates/django_admin

e como você pode ver, depende da versão do python e da pasta onde o Django instalou. Portanto, no futuro ou em um servidor de produção, talvez seja necessário alterar o caminho.


0

Este site tinha uma solução simples que funcionava com a minha configuração do Django 1.7.

PRIMEIRO: Crie um link simbólico chamado admin_src no diretório / template do seu projeto para os modelos Django instalados. Para mim no Dreamhost usando um virtualenv, meus modelos de administração do Django "fonte" estavam em:

~/virtualenvs/mydomain/lib/python2.7/site-packages/django/contrib/admin/templates/admin

SEGUNDO: Crie um diretório administrativo em templates /

Portanto, o diretório / modelo do meu projeto agora fica assim:

/templates/
   admin
   admin_src -> [to django source]
   base.html
   index.html
   sitemap.xml
   etc...

TERCEIRO: No seu novo diretório template / admin /, crie um arquivo base.html com este conteúdo:

{% extends "admin_src/base.html" %}

{% block extrahead %}
<link rel='shortcut icon' href='{{ STATIC_URL }}img/favicon-admin.ico' />
{% endblock %}

QUARTA: Adicione seu admin favicon-admin.ico na sua pasta estática de img raiz.

Feito. Fácil.


0

para o índice do aplicativo, adicione esta linha a um arquivo py em algum lugar comum, como url.py

admin.site.index_template = 'admin/custom_index.html'

para índice de módulo de aplicativo: adicione esta linha ao admin.py

admin.AdminSite.app_index_template = "servers/servers-home.html"

para lista de alterações: adicione esta linha à classe admin:

change_list_template = "servers/servers_changelist.html"

para modelo de formulário do módulo de aplicativo: adicione esta linha à sua classe de administrador

change_form_template = "servers/server_changeform.html"

etc. e encontre outros nas mesmas classes de módulos do administrador


-1

Você pode usar o django-overextends , que fornece herança circular de modelos para o Django.

Ele vem do Mezzanine CMS, de onde Stephen o extraiu para uma extensão autônoma do Django.

Mais informações que você encontra em "Substituindo modelos extensíveis" (http: /mezzanine.jupo.org/docs/content-architecture.html#overriding-vs-extending-templates) nos documentos do Mezzanine.

Para informações mais aprofundadas, consulte o Stephens Blog "Herança de modelo circular para Django" (http: /blog.jupo.org/2012/05/17/circular-template-inheritance-for-django).

E nos Grupos do Google a discussão (https: /groups.google.com/forum / #! Topic / mezzanine-users / sUydcf_IZkQ) que iniciou o desenvolvimento desse recurso.

Nota:

Não tenho reputação de adicionar mais de 2 links. Mas acho que os links fornecem informações interessantes. Então, deixei de fora uma barra após "http (s):". Talvez alguém com melhor reputação possa reparar os links e remover esta nota.


Desde o Django 1.9, este projeto não é relevante, o mantenedor simplesmente não o está anunciando, veja code.djangoproject.com/ticket/15053 e github.com/stephenmcd/django-overextends/pull/37 . Para assumir o controle completo de qual aplicativo um modelo é carregado, há o django-apptemplates e o django-app-namespace-template-loader, que ainda são relevantes se você deseja estender de um aplicativo para outro.
— benjaoming 22/07
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.