Как переопределить и расширить базовые шаблоны администратора Django?


127

Как переопределить шаблон администратора (например, admin / index.html), одновременно расширив его (см. Https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing -an-admin-template )?

Во-первых, я знаю, что этот вопрос уже задавался, и на него уже были даны ответы (см. Django: переопределение и расширение шаблона приложения ), но, как говорится в ответе, он не применим напрямую, если вы используете загрузчик шаблонов app_directories (который является большей частью время).

Мой текущий обходной путь состоит в том, чтобы делать копии и расширять их, вместо того, чтобы расширять непосредственно из шаблонов администратора. Это отлично работает, но действительно сбивает с толку и добавляет дополнительную работу при изменении шаблонов администратора.

Можно подумать о каком-то настраиваемом теге расширения для шаблонов, но я не хочу изобретать велосипед, если решение уже существует.

На заметку: кто-нибудь знает, будет ли эта проблема решена самим Django?


1
Копирование шаблонов администратора, их расширение и переопределение / добавление блоков - наиболее эффективный, хотя и не оптимальный рабочий процесс с учетом текущего состояния Django. Я не видел другого способа сделать то, что вы пытаетесь сделать за три года работы с этим :)
— Брэндон

Что ж, я не знаю, хорошо это или плохо, но, по крайней мере, такие люди, как вы, пришли к такому же выводу. Приятно слышать. :)
— Semmel

Ответы:


101

Обновление :

Прочтите документацию для своей версии Django. например

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 -templates

Оригинальный ответ от 2011 года:

У меня была такая же проблема около полутора лет назад, и я нашел на djangosnippets.org хороший загрузчик шаблонов, который упрощает эту задачу . Он позволяет расширять шаблон в конкретном приложении, давая вам возможность создать свой собственный admin / index.html, который расширяет шаблон admin / index.html из приложения администратора. Как это:

{% 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 %}

Я привел полный пример того, как использовать этот загрузчик шаблонов, в сообщении в блоге на моем веб-сайте.


18
Для справки; рассматриваемый фрагмент был преобразован в приложение django и доступен в PyPi (pip / easy_install) как django-apptemplates: pypi.python.org/pypi/django-apptemplates
— Romløk

9
Чтобы быть на 100% точным: указанное выше решение НЕ БУДЕТ БОЛЬШЕ РАБОТАТЬ для последних версий Django (как минимум 1.4), поскольку одна из функций, используемых скриптом, обесценилась. Вы можете найти обновленный источник здесь
— OldTinfoil

2
Обратите внимание, что с Django 1.8 это по-прежнему будет работать, но настройку нужно производить особым образом (см. Пример настройки app_namespace.Loader ). django-app-namespace-template-loader также является рабочей альтернативой, django-apptemplatesесли он может перестать работать однажды.
— Петерино

Этот ответ был очень хорош для старых версий Django. Но на данный момент более актуален другой ответ Чэна. stackoverflow.com/a/29997719/7344164
— SoftwareEnggUmar

70

Что касается Django 1.8, являющегося текущим выпуском, нет необходимости создавать символические ссылки, копировать admin / templates в папку вашего проекта или устанавливать промежуточное ПО, как это предлагается в ответах выше. Вот что надо делать:

  1. создать следующую древовидную структуру (рекомендуется официальной документацией )

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

Примечание . Местоположение этого файла не имеет значения. Вы можете поместить его в свое приложение, и оно все равно будет работать. Если его местоположение может быть обнаружено с помощью django. Что более важно, имя HTML-файла должно совпадать с исходным именем HTML-файла, предоставленным django.

  1. Добавьте этот путь к шаблону в свой settings.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. Определите имя и блок, который вы хотите переопределить. Это можно сделать, заглянув в каталог django admin / templates. Я использую virtualenv, поэтому для меня путь здесь:

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

В этом примере я хочу изменить форму добавления нового пользователя. Шаблон, отвечающий за это представление, - change_form.html . Откройте change_form.html и найдите {% block%}, который вы хотите расширить.

  1. В вашем change_form.html напишите что-нибудь вроде этого:

    {% extends "admin/change_form.html" %}
    {% block field_sets %}
         {# your modification here #}
    {% endblock %}
  2. Загрузите свою страницу, и вы увидите изменения


Этого все же недостаточно для расширения основного шаблона index.html без копирования всех блоков. Решение состоит в том, чтобы записать некоторые из них ../в «расширяющий» путь и указать более уникальный исходный путь {% extends "../../admin/templates/admin/index.html" %}. ссылка на ответ
— hynekcer

1
Я думаю, что в TEMPLATES мы должны использовать 'DIRS': [os.path.join (BASE_DIR, 'templates')],
— Рауль Рейес

Это тип потока, который прекрасно иллюстрирует недостаток SO. Фреймворк обновляется, и вопрос больше не актуален, он фактически является сдерживающим фактором от правильного пути. Отличный ответ здесь. RTFM kids.
— Дерек Адэр

Спасибо за этот ответ. За исключением «Местоположение этого файла не имеет значения», все работало отлично.
— Jaswanth Manigundan

54

если вам нужно перезаписать файлadmin/index.html , вы можете установить параметр index_template файлаAdminSite .

например

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

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

и поместите свой шаблон в <appname>/templates/admin/my_custom_index.html


5
Brilliant! Это позволяет вам сделать это {% extends "admin/index.html" %}из my_custom_index.html и иметь ссылку на шаблон администратора django, не копируя его. Спасибо.
— mattmc3

3
@Semmel должен отметить это как правильный ответ, поскольку это простейший подход, использующий встроенные функции django и не требующий использования пользовательских загрузчиков шаблонов.
— MrColes

17

С django1.5 (по крайней мере) вы можете определить шаблон, который хотите использовать для определенногоmodeladmin

см. https://docs.djangoproject.com/en/1.5/ref/contrib/admin/#custom-template-options

Вы можете сделать что-то вроде

class Myadmin(admin.ModelAdmin):
    change_form_template = 'change_form.htm'

С change_form.htmlрасширением простого шаблона html admin/change_form.html(или нет, если вы хотите сделать это с нуля)


9

Ответ Ченгса правильный, однако, согласно документам администратора, не каждый шаблон администратора может быть перезаписан таким образом: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#overriding-admin-templates

Шаблоны, которые можно переопределить для каждого приложения или модели

Не каждый шаблон в contrib / admin / templates / admin можно переопределить для каждого приложения или модели. Следующее может:

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

Для тех шаблонов, которые нельзя переопределить таким образом, вы все равно можете переопределить их для всего проекта. Просто поместите новую версию в свой каталог templates / admin . Это особенно полезно для создания пользовательских страниц 404 и 500.

Мне пришлось перезаписать login.html администратора и поэтому пришлось поместить перезаписанный шаблон в эту структуру папок:

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

(без подпапки myapp в админке) У меня недостаточно репутации для того, чтобы комментировать сообщение Ченга, поэтому мне пришлось написать это как новый ответ.


Спасибо за обратную связь, hyneker. Надеюсь, теперь мой ответ более ясен и точен.
— matyas

Да, полезно знать, что шаблоны можно настраивать на уровне проекта, даже если некоторые из них могут быть изменены произвольно на уровне приложения.
— hynekcer

5

Лучший способ сделать это - поместить шаблоны администратора Django в свой проект. Таким образом, ваши шаблоны будут в templates/adminналичии, в то время как стандартные шаблоны администратора Django будут присутствовать template/django_admin. Затем вы можете сделать что-то вроде следующего:

шаблоны / администратор / change_form.html

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

Your stuff here

Если вы беспокоитесь об обновлении стандартных шаблонов, вы можете включить их с помощью svn externals или аналогичного.


Использование svn externals - отличная идея. Проблема в том, что все мои переводчики будут переводить все эти шаблоны (потому что makemessages будет собирать строки перевода из всех шаблонов администратора), что добавляет много дополнительной работы, если вы работаете с несколькими языками. Может быть, есть способ исключить эти шаблоны из makemessages?
— Semmel

Используйте --ignoreаргумент с makemessages. См .: docs.djangoproject.com/en/dev/ref/django-admin/#makemessages
— Крис Пратт

Я думаю, что другой ответ мне больше подходит. Но мне нравится ваше решение, и я думаю, что это хорошая альтернатива, если вы не хотите возиться с загрузчиками шаблонов.
— Semmel

5

Я не смог найти ни одного ответа или раздела в официальных документах Django, в котором была бы вся информация, необходимая мне для переопределения / расширения шаблонов администратора по умолчанию, поэтому я пишу этот ответ как полное руководство, надеясь, что это будет полезно для других в будущем.

Предполагая стандартную структуру проекта 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/

Вот что вам нужно сделать:

  1. В mysite/admin.pyсоздайте подкласс 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()

    Обязательно импортируйте custom_admin_siteв admin.pyсвои приложения и зарегистрируйте в нем свои модели, чтобы отображать их на настраиваемом сайте администратора (если хотите).

  2. В mysite/apps.py, создайте подкласс AdminConfigи установите default_siteзначение admin.CustomAdminSiteиз предыдущего шага:

    from django.contrib.admin.apps import AdminConfig
    
    
    class CustomAdminConfig(AdminConfig):
        default_site = 'admin.CustomAdminSite'
  3. В mysite/settings.pyзамените django.admin.sitein INSTALLED_APPSна apps.CustomAdminConfig(конфигурация пользовательского приложения администратора из предыдущего шага).

  4. В mysite/urls.pyзамените admin.site.urlsURL-адрес администратора наcustom_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. Создайте шаблон, который вы хотите изменить, в своем templatesкаталоге, сохранив структуру каталогов шаблонов администратора Django по умолчанию, как указано в документации . Например, если вы вносили изменения admin/index.html, создайте файл templates/admin/index.html.

    Таким образом можно изменить все существующие шаблоны, а их имена и структуры можно найти в исходном коде Django .

  6. Теперь вы можете либо переопределить шаблон, написав его с нуля, либо расширить, а затем переопределить / расширить определенные блоки.

    Например, если вы хотите сохранить все как есть, но хотите переопределить contentблок (который на индексной странице содержит список приложений и их моделей, которые вы зарегистрировали), добавьте следующее в templates/admin/index.html:

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

    Чтобы сохранить исходное содержимое блока, добавьте {{ block.super }}туда , где вы хотите, чтобы исходное содержимое отображалось:

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

    Вы также можете добавлять пользовательские стили и скрипты, изменив extrastyleи extraheadблоки.


у вас есть источник или документация по этому поводу?
— Мэри

Кроме двух ссылок, которые я добавил в пункте 5, нет, у меня больше ничего нет.
— Фахил,

1

Я согласен с Крисом Праттом. Но я думаю, что лучше создать символическую ссылку на исходную папку Django, в которую помещаются шаблоны администратора:

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

и, как видите, это зависит от версии Python и папки, в которой установлен Django. Так что в будущем или на рабочем сервере вам может потребоваться изменить путь.


0

это сайте было простое решение, которое работало с моей конфигурацией Django 1.7.

ПЕРВЫЙ: создайте символическую ссылку с именем admin_src в каталоге template / вашего проекта на установленные вами шаблоны Django. Для меня на Dreamhost, использующего virtualenv, мои "исходные" шаблоны администратора Django находились в:

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

ВТОРОЙ: Создайте административный каталог в templates /

Итак, каталог / шаблон моего проекта теперь выглядел так:

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

ТРЕТИЙ: В вашем новом каталоге template / admin / создайте файл base.html с таким содержимым:

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

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

ЧЕТВЕРТОЕ: Добавьте своего администратора favicon-admin.ico в свою статическую корневую папку img.

Готово. Легко.


0

для индекса приложения добавьте эту строку в какой-нибудь общий файл py, например url.py

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

для индекса модуля приложения: добавьте эту строку в admin.py

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

для списка изменений: добавьте эту строку в класс администратора:

change_list_template = "servers/servers_changelist.html"

для шаблона формы модуля приложения: добавьте эту строку в свой класс администратора

change_form_template = "servers/server_changeform.html"

и т.д. и найдите другие в тех же классах модуля администратора


-1

Вы можете использовать django-overextends , который обеспечивает циклическое наследование шаблонов для Django.

Он взят из Mezzanine CMS, откуда Стивен извлек его в отдельное расширение Django.

Дополнительную информацию вы найдете в разделе «Переопределение и расширение шаблонов» (http: /mezzanine.jupo.org/docs/content-architecture.html#overriding-vs-exnding-templates) внутри документации Mezzanine.

Для более глубокого понимания загляните в блог Стивенса «Наследование круговых шаблонов для Django» (http: /blog.jupo.org/2012/05/17/circular-template-inheritance-for-django).

И в группах Google обсуждение (https: /groups.google.com/forum / #! Topic / mezzanine-users / sUydcf_IZkQ), положившее начало разработке этой функции.

Примечание:

У меня нет репутации добавлять больше двух ссылок. Но я думаю, что ссылки предоставляют интересную справочную информацию. Поэтому я просто опустил косую черту после «http (s):». Может быть, кто-нибудь с лучшей репутацией сможет восстановить ссылки и удалить эту заметку.


Начиная с Django 1.9, этот проект не был актуальным, разработчик просто не рекламировал его, см. Code.djangoproject.com/ticket/15053 и github.com/stephenmcd/django-overextends/pull/37 . Чтобы полностью контролировать, из какого приложения загружается шаблон, есть django-apptemplates и django-app-namespace-template-loader, которые по-прежнему актуальны, если вы хотите перейти от одного приложения к другому.
— benjaoming
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.