Как переопределить и расширить базовые шаблоны администратора 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.