基本的なDjango管理テンプレートをオーバーライドして拡張する方法


125

管理テンプレート(例:admin / index.html)をオーバーライドすると同時に、それを拡張する方法(https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacingを参照) -an-admin-template)?

最初に、この質問が以前に尋ねられて回答されたことを知っていますが(Django:アプリテンプレートのオーバーライドと拡張を参照)、答えが言うように、app_directoriesテンプレートローダー(ほとんどの場合)を使用している場合、これは直接適用できません。時間)。

現在の回避策は、管理テンプレートから直接拡張するのではなく、コピーを作成してそれらから拡張することです。これはうまく機能しますが、それは本当に混乱し、管理テンプレートが変更されると余分な作業が追加されます。

テンプレート用のカスタム拡張タグを考えることができますが、すでに解決策が存在する場合は、ホイールを再発明したくありません。

余談ですが、この問題がDjango自体によって解決されるかどうか誰かが知っていますか?


1
Djangoの現在の状態を考えると、ワークフローは最適ではありませんが、管理テンプレートをコピーして拡張し、ブロックをオーバーライド/追加することが最も効率的です。私はそれを使って3年間であなたがしようとしていることを行う他の方法を見たことはありません:)
Brandon

まあ-これが良いことかどうかはわかりませんが、少なくともあなたのような人々は同じ結論に達しています。よかったね。:)
センメル

回答:


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 -テンプレート

2011年の元の回答:

私は1年半ほど前に同じ問題を抱えていましたが、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 %}

このテンプレートローダーを使用する方法の完全な例を、私のWebサイトのブログ投稿で紹介しました。


18
参考のため; :当該断片は、Djangoアプリケーションに変換され、は、PyPIに入手可能である(PIP / easy_installを)ジャンゴ-apptemplatesとしてれているpypi.python.org/pypi/django-apptemplates
Romløk

9
100%明示的であること:上記のソリューションは、Djangoの最近のバージョン(少なくとも1.4)では機能しません。スクリプトが使用する関数の1つが廃止されているためです。 更新されたソースはこちら
OldTinfoil 2013年

2
Django 1.8でもこれは機能しますが、セットアップは特別な方法で行う必要があることに注意してください(例としてapp_namespace.Loaderのセットアップを参照してください)。django-app-namespace-template-loaderも、django-apptemplatesある日機能しなくなる可能性がある場合の代わりとして機能します。
Peterino、2015

この回答は、古いDjangoバージョンには非常に適していました。しかし、現時点では、Chengによる別の回答の方が関連しています。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ファイルの名前は、djangoによって提供された元のHTMLファイル名と同じでなければならないということです。

  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」テンプレートを拡張するにはまだ十分ではありません。解決策は、いくつか../を "exendds"パスに書き込み、元のパスをより一意に指定すること{% extends "../../admin/templates/admin/index.html" %}です。回答へのリンク
hynekcer

1
TEMPLATESでは、 'DIRS'を使用する必要があると思います:[os.path.join(BASE_DIR、 'templates')]、
Raul Reyes

これは、SOの欠陥を完全に示すタイプのスレッドです。フレームワークは更新され、質問はもはや関係ありません、それは実際には適切なパスからの抑止力です。ここで素晴らしい答えです。RTFMキッズ。
Derek Adair

この回答をありがとう。「このファイルの場所は重要ではありません。」を除いて、すべてがうまくいきました。
Jaswanth Manigundan 2017年

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
鮮やかさ!これにより{% extends "admin/index.html" %}、my_custom_index.htmlからdjango管理テンプレートをコピーしなくても参照できるようになります。ありがとうございました。
mattmc3

3
@Semmelは、組み込みのdjango機能を使用する最も単純なアプローチであり、カスタムテンプレートローダーを使用する必要がないため、これを正しい答えとしてマークする必要があります。
MrColes

17

django(少なくとも)1.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

人のために上書きすることができないテンプレートこのように、あなたはまだ全体のプロジェクトのためにそれらを無効にすることができます。ただ、置くあなたに新しいバージョンをテンプレート/管理ディレクトリ。これは、カスタム404および500ページを作成するのに特に役立ちます

管理者のlogin.htmlを上書きする必要があったため、上書きしたテンプレートをこのフォルダー構造に配置する必要がありました。

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

(管理者にmyappサブフォルダーがない場合)Chengの投稿にコメントする十分な評判がないため、これを新しい回答として作成する必要がありました。


フィードバックハイネカーをありがとうございました。私の答えがより明確になり、より真っ直ぐになりました。
matyas

はい。テンプレートの一部をアプリケーションレベルでオプションで変更できる場合でも、プロジェクトレベルでテンプレートをカスタマイズできることを知っておくと便利です。
hynekcer 2016

5

これを行う最良の方法は、Django管理テンプレートをプロジェクト内に配置することです。ですから、あなたのテンプレートはありますが、templates/adminDjangoの標準の管理用テンプレートはそうtemplate/django_adminです。その後、次のようなことができます。

templates / admin / change_form.html

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

Your stuff here

ストックテンプレートを最新の状態に保つことが心配な場合は、svn externalsなどを使用してテンプレートを含めることができます。


svn externalsの使用は素晴らしいアイデアです。これがもたらす問題は、すべての翻訳者がそれらすべてのテンプレートを翻訳することです(makemessagesはすべての管理テンプレートから翻訳文字列を収集するため)。これにより、複数の言語で作業している場合、多くの追加作業が追加されます。たぶん、それらのテンプレートをmakemessagesから除外する方法はありますか?
センメル

--ignore引数をとともに使用しますmakemessages。参照:docs.djangoproject.com/en/dev/ref/django-admin/#makemessages
Chris Pratt

他の答えは私のニーズによりよく合っていると思います。しかし、私はあなたのソリューションが好きで、テンプレートローダーをいじりたくない場合は、それが良い代替案だと思います。
センメル

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_siteadmin.pyてモデルを登録し、カスタマイズした管理サイトに表示してください。

  2. で、前の手順ののmysite/apps.pyサブクラスを作成し、にAdminConfig設定default_siteadmin.CustomAdminSiteます。

    from django.contrib.admin.apps import AdminConfig
    
    
    class CustomAdminConfig(AdminConfig):
        default_site = 'admin.CustomAdminSite'
  3. で、を(前のステップのカスタム管理アプリ構成mysite/settings.py)に置き換えます。django.admin.siteINSTALLED_APPSapps.CustomAdminConfig

  4. mysite/urls.py、置き換えadmin.site.urlsに管理URLから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. docsでtemplates指定されているデフォルトのDjango管理テンプレートディレクトリ構造を維持しながら、変更するテンプレートをディレクトリに作成します。たとえば、変更していた場合は、ファイルを作成します。admin/index.htmltemplates/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で追加した2つの参照以外は、いいえ、他に何もありません。
Faheel

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構成で機能するシンプルなソリューションがありました。

FIRST:シンボリックリンクの名前確認しadmin_srcインストールしたDjangoのテンプレートにプロジェクトのテンプレート/ディレクトリ内に。Dreamenvでvirtualenvを使用している場合、「ソース」のDjango管理テンプレートは次の場所にあります。

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

2番目: templates /にadminディレクトリを作成します

だから私のプロジェクトのテンプレート/ディレクトリは次のようになりました:

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

3 番目新しいtemplate / admin /ディレクトリに、次の内容のbase.htmlファイルを作成します。

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

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

4番目静的ルートのimgフォルダーに管理者favicon-admin.icoを追加します。

できました。簡単です。


0

アプリインデックスの場合、この行をurl.pyなどの一般的な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に循環テンプレートの継承を提供するdjango-overextendsを使用できます。

これはメザニン CMSからのもので、StephenはそれをスタンドアロンのDjango拡張機能に抽出しました。

詳細については、メザニンドキュメント内の「テンプレートのオーバーライドと拡張」(http:/mezzanine.jupo.org/docs/content-architecture.html#overriding-vs-extending-templates)を参照してください。

詳細については、Stephensブログの「Djangoの循環テンプレート継承」(http:/blog.jupo.org/2012/05/17/circular-template-inheritance-for-django)をご覧ください。

そして、Googleグループでは、この機能の開発を開始した議論(https:/groups.google.com/forum /#!topic / mezzanine-users / sUydcf_IZkQ)が行われました。

注意:

2つを超えるリンクを追加するという評判はありません。しかし、リンクは興味深い背景情報を提供すると思います。そのため、「http(s):」の後ろのスラッシュは省略しました。評判の良い人がリンクを修正して、このメモを削除できるでしょう。


Django 1.9以降、このプロジェクトは関連性がなく、メンテナはそれを宣伝していません。code.djangoproject.com / ticket / 15053およびgithub.com/stephenmcd/django-overextends/pull/37を参照してください。テンプレートのロード元のアプリを完全に制御するために、django-apptemplatesとdjango-app-namespace-template-loaderがあります。これらはどちらも、1つのアプリから別のアプリに拡張する場合に関連します。
ベンジャオミング
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.