Bagaimana menimpa dan memperluas cetakan admin Django dasar?

126

Bagaimana cara mengganti template admin (mis. Admin / index.html) sementara pada saat yang sama memperluasnya (lihat https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing -an-admin-template )?

Pertama - Saya tahu bahwa pertanyaan ini telah ditanyakan dan dijawab sebelumnya (lihat Django: Menimpa DAN memperluas templat aplikasi ) tetapi karena jawabannya mengatakan itu tidak berlaku langsung jika Anda menggunakan pemuat templat app_directories (yang merupakan sebagian besar waktu).

Solusi saya saat ini adalah membuat salinan dan memperluasnya alih-alih memperluas langsung dari templat admin. Ini berfungsi dengan baik tetapi sangat membingungkan dan menambahkan pekerjaan ekstra saat template admin berubah.

Itu bisa memikirkan beberapa ekstensi-tag khusus untuk template tetapi saya tidak ingin menemukan kembali roda jika sudah ada solusi.

Di samping catatan: Adakah yang tahu jika masalah ini akan ditangani oleh Django sendiri?

Semmel
sumber
1
Menyalin templat admin, memperluasnya dan menimpa / menambah blok adalah yang paling efisien, walaupun alur kerja tidak optimal mengingat keadaan Django saat ini. Saya belum melihat cara lain untuk melakukan apa yang Anda coba lakukan selama tiga tahun bekerja dengannya :)
Brandon
Yah - saya tidak tahu apakah ini hal yang baik atau tidak tetapi setidaknya orang-orang seperti Anda sampai pada kesimpulan yang sama. Itu terdengar baik. :)
Semmel

Jawaban:

101

Pembaruan :

Bacalah Docs untuk versi Django Anda. misalnya

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

Jawaban asli dari 2011:

Saya mengalami masalah yang sama sekitar satu setengah tahun yang lalu dan saya menemukan pemuat template yang bagus di djangosnippets.org yang membuatnya mudah. Ini memungkinkan Anda untuk memperluas template di aplikasi tertentu, memberi Anda kemampuan untuk membuat admin / index.html Anda sendiri yang memperluas template admin / index.html dari aplikasi admin. Seperti ini:

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

Saya telah memberikan contoh lengkap tentang cara menggunakan pemuat template ini dalam posting blog di situs web saya.

Hei bro
sumber
18
Sebagai referensi; potongan yang dimaksud telah diubah menjadi aplikasi django, dan tersedia dalam PyPi (pip / easy_install) sebagai django-apptemplates: pypi.python.org/pypi/django-apptemplates
Romløk
9
Hanya untuk menjadi 100% eksplisit: solusi di atas TIDAK AKAN BEKERJA LAGI untuk versi terbaru dari Django (setidaknya 1.4), karena salah satu fungsi yang digunakan skrip dikurangi. Anda dapat menemukan sumber yang diperbarui di sini
OldTinfoil
2
Catat bahwa dengan Django 1.8 ini masih akan bekerja, tetapi penataan perlu dibuat dengan cara khusus (lihat penyiapan app_namespace.Loader sebagai contoh). django-app-namespace-template-loader juga merupakan alternatif yang berfungsi django-apptemplatesjika mungkin berhenti bekerja suatu hari nanti.
Peterino
Jawaban ini sangat bagus untuk versi Django yang lebih lama. Tapi sekarang, jawaban lain dari Cheng lebih relevan. stackoverflow.com/a/29997719/7344164
SoftwareEnggUmar
70

Adapun Django 1.8 menjadi terbitan saat ini, tidak perlu symlink, salin admin / templates ke folder proyek Anda, atau instal middlewares seperti yang disarankan oleh jawaban di atas. Inilah yang harus dilakukan:

  1. buat struktur pohon berikut (direkomendasikan oleh dokumentasi resmi )

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

Catatan : Lokasi file ini tidak penting. Anda dapat memasukkannya ke dalam aplikasi Anda dan itu akan tetap berfungsi. Asalkan lokasinya bisa ditemukan oleh django. Yang lebih penting adalah nama file HTML harus sama dengan nama file HTML asli yang diberikan oleh django.

  1. Tambahkan jalur templat ini ke pengaturan Anda.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. Identifikasi nama dan blokir yang ingin Anda timpa. Ini dilakukan dengan melihat ke dalam direktori admin / templates django. Saya menggunakan virtualenv, jadi bagi saya, jalurnya ada di sini:

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

Dalam contoh ini, saya ingin mengubah formulir tambah pengguna baru. Template responsiblve untuk tampilan ini adalah change_form.html . Buka change_form.html dan temukan {% block%} yang ingin Anda perpanjang.

  1. Di change_form.html Anda , tulis sesuatu seperti ini:

    {% extends "admin/change_form.html" %}
    {% block field_sets %}
         {# your modification here #}
    {% endblock %}
  2. Muat halaman Anda dan Anda akan melihat perubahannya

Cheng
sumber
Ini masih belum cukup untuk memperpanjang template utama "index.html", tanpa menyalin semua blok. Solusinya adalah dengan menulis beberapa ../ke jalur "exetends" dan menentukan jalur asli yang lebih unik {% extends "../../admin/templates/admin/index.html" %}. tautan ke jawaban
hynekcer
1
Saya pikir di TEMPLATES kita harus menggunakan 'DIRS': [os.path.join (BASE_DIR, 'templates')],
Raul Reyes
Ini adalah jenis utas yang secara sempurna menggambarkan cacat pada SO. Kerangka kerja diperbarui dan pertanyaannya tidak lagi relevan, itu sebenarnya adalah penghalang dari jalur yang tepat. Jawaban yang bagus di sini. Anak-anak RTFM.
Derek Adair
Terima kasih atas jawaban ini. Kecuali untuk "Lokasi file ini tidak penting.", Semuanya bekerja dengan baik.
Jaswanth Manigundan
54

jika Anda perlu menimpa admin/index.html, Anda dapat menyetel parameter index_template dari AdminSite.

misalnya

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

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

dan tempatkan template Anda <appname>/templates/admin/my_custom_index.html

jahe
sumber
5
Cemerlang! Melakukan ini memungkinkan Anda untuk kemudian melakukan {% extends "admin/index.html" %}dari my_custom_index.html dan memiliki referensi template admin django tanpa menyalinnya. Terima kasih.
mattmc3
3
@Semmel harus menandai ini sebagai jawaban yang benar, karena ini adalah pendekatan paling sederhana yang menggunakan fitur django bawaan dan tidak perlu menggunakan pemuat template khusus.
MrColes
17

Dengan django1,5 (setidaknya) Anda dapat menentukan template yang ingin Anda gunakan untuk tertentumodeladmin

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

Anda bisa melakukan sesuatu seperti

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

Dengan change_form.htmlekstensi template html sederhana admin/change_form.html(atau tidak jika Anda ingin melakukannya dari awal)

maazza
sumber
9

Jawaban Chengs benar, namun menurut dokumen admin tidak setiap template admin dapat ditimpa dengan cara ini: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#overriding-admin-templates

Template yang dapat diganti per aplikasi atau model

Tidak setiap template di contrib / admin / templates / admin dapat diganti per aplikasi atau per model. Berikut ini dapat:

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

Untuk template yang tidak dapat diganti dengan cara ini, Anda masih dapat menimpanya untuk seluruh proyek Anda. Cukup tempatkan versi baru di direktori templates / admin Anda . Ini sangat berguna untuk membuat halaman 404 dan 500 tersuai

Saya harus menimpa login.html admin dan oleh karena itu harus meletakkan template yang ditimpa dalam struktur folder ini:

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

(tanpa subfolder myapp di admin) Saya tidak memiliki cukup reputasi untuk mengomentari posting Cheng, inilah mengapa saya harus menulis ini sebagai jawaban baru.

matyas
sumber
Terima kasih atas umpan balik hyneker semoga jawaban saya lebih jelas dan lebih langsung ke intinya sekarang.
matyas
Ya, sangatlah berguna untuk mengetahui bahwa templat dapat disesuaikan pada tingkat proyek meskipun beberapa di antaranya dapat diubah secara opsional pada tingkat aplikasi.
hynekcer
5

Cara terbaik untuk melakukannya adalah dengan meletakkan cetakan admin Django di dalam proyek Anda. Jadi cetakan anda akan berada di templates/adminsementara cetakan admin stok Django akan di katakan template/django_admin. Kemudian, Anda dapat melakukan sesuatu seperti berikut:

templates / admin / change_form.html

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

Your stuff here

Jika Anda khawatir tentang memperbarui templat stok, Anda dapat memasukkannya dengan svn eksternal atau serupa.

Chris Pratt
sumber
Menggunakan svn eksternal adalah ide bagus. Masalah yang diperkenalkan ini adalah bahwa semua penerjemah saya akan menerjemahkan semua templat itu (karena makemessages akan mengumpulkan string terjemahan dari semua templat admin) yang menambahkan banyak pekerjaan ekstra jika Anda bekerja dengan banyak bahasa. Mungkin ada cara untuk mengecualikan template tersebut dari makemessages?
Semmel
Gunakan --ignoreargumen dengan makemessages. Lihat: docs.djangoproject.com/en/dev/ref/django-admin/#makemessages
Chris Pratt
Saya pikir jawaban yang lain lebih sesuai dengan kebutuhan saya. Tetapi saya menyukai solusi Anda dan menganggapnya sebagai alternatif yang baik jika Anda tidak ingin dipusingkan dengan pemuat template Anda.
Semmel
5

Saya tidak dapat menemukan satu jawaban atau satu bagian dalam dokumen resmi Django yang memiliki semuanya informasi yang saya butuhkan untuk menimpa / memperluas templat admin default, jadi saya menulis jawaban ini sebagai panduan lengkap, berharap itu akan membantu untuk orang lain di masa depan.

Dengan asumsi struktur proyek Django standar:

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/

Inilah yang perlu Anda lakukan:

  1. Di mysite/admin.py, buat sub-kelas dari 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()

    Pastikan untuk mengimpor custom_admin_sitedi admin.pyaplikasi Anda dan mendaftarkan model Anda di atasnya untuk menampilkannya di situs admin kustom Anda (jika Anda mau).

  2. Di mysite/apps.py, buat sub-kelas dari AdminConfigdan setel default_siteke admin.CustomAdminSitedari langkah sebelumnya:

    from django.contrib.admin.apps import AdminConfig
    
    
    class CustomAdminConfig(AdminConfig):
        default_site = 'admin.CustomAdminSite'
  3. Dalam mysite/settings.py, ganti django.admin.sitedi INSTALLED_APPSdengan apps.CustomAdminConfig(Anda admin kustom aplikasi konfigurasi dari langkah sebelumnya).

  4. Masuk mysite/urls.py, ganti admin.site.urlsdari URL admin menjadicustom_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. Buat templat yang ingin Anda ubah dalam templatesdirektori Anda , pertahankan struktur direktori templat admin Django default seperti yang ditentukan dalam dokumen . Misalnya, jika Anda memodifikasi admin/index.html, buat file templates/admin/index.html.

    Semua templat yang ada dapat dimodifikasi dengan cara ini, dan nama serta strukturnya dapat ditemukan dalam kode sumber Django .

  6. Sekarang Anda dapat mengganti template dengan menulisnya dari awal atau memperluasnya dan kemudian mengganti / memperluas blok tertentu.

    Misalnya, jika Anda ingin menyimpan semuanya sebagaimana adanya tetapi ingin menimpa contentblokir (yang di halaman indeks mencantumkan aplikasi dan modelnya yang Anda daftarkan), tambahkan yang berikut ini ke templates/admin/index.html:

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

    Untuk mempertahankan konten asli blok, tambahkan di {{ block.super }}mana pun Anda ingin konten asli ditampilkan:

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

    Anda juga dapat menambahkan gaya dan skrip kustom dengan memodifikasi blok extrastyledan extrahead.

Faheel
sumber
apakah Anda memiliki sumber atau dokumentasi tentang ini?
Mary
Terlepas dari dua referensi yang saya tambahkan di poin 5, tidak, saya tidak punya yang lain.
Faheel
1

Saya setuju dengan Chris Pratt. Tetapi saya pikir lebih baik membuat symlink ke folder Django asli dimana template admin ditempatkan di:

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

dan seperti yang Anda lihat itu tergantung pada versi python dan map tempat Django dipasang. Jadi di masa mendatang atau di server produksi, Anda mungkin perlu mengubah jalurnya.

James May
sumber
0

IniSitus mempunyai solusi sederhana yang bekerja dengan konfigurasi Django 1.7 saya.

PERTAMA: Buatlah sebuah symlink bernama admin_src dalam direktori template / proyek Anda ke template Django yang Anda instal. Bagi saya di Dreamhost menggunakan virtualenv, templat admin Django "sumber" saya ada di:

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

KEDUA: Buat direktori admin di templates /

Jadi template / direktori proyek saya sekarang terlihat seperti ini:

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

KETIGA: Di direktori template / admin / baru Anda, buat file base.html dengan konten ini:

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

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

KEEMPAT: Tambahkan favicon-admin.ico admin Anda ke folder img root statis Anda.

Selesai. Mudah.

mitchf
sumber
0

untuk indeks aplikasi, tambahkan baris ini ke file py umum seperti url.py

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

untuk indeks modul aplikasi: tambahkan baris ini ke admin.py

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

untuk daftar perubahan: tambahkan baris ini ke kelas admin:

change_list_template = "servers/servers_changelist.html"

untuk templat formulir modul aplikasi: tambahkan baris ini ke kelas admin Anda

change_form_template = "servers/server_changeform.html"

dll. dan temukan yang lain di kelas modul admin yang sama

Saurabh Chandra Patel
sumber
-1

Anda bisa menggunakan django-overextends , yang menyediakan warisan templat melingkar untuk Django.

Itu berasal dari CMS Mezanin , dari mana Stephen mengekstraknya menjadi ekstensi Django mandiri.

Info selengkapnya yang Anda temukan di "Overriding vs Extending Templates" (http: /mezzanine.jupo.org/docs/content-architecture.html#overriding-vs-extending-templates) di dalam dokumen Mezzanine.

Untuk bagian dalam yang lebih dalam, lihat Blog Stephens "Warisan Templat Edaran untuk Django" (http: /blog.jupo.org/2012/05/17/circular-template-inheritance-for-django).

Dan di Google Grup, diskusi (https: /groups.google.com/forum / #! Topic / mezzanine-users / sUydcf_IZkQ) yang memulai pengembangan fitur ini.

catatan:

Saya tidak memiliki reputasi untuk menambahkan lebih dari 2 tautan. Tapi menurut saya tautannya memberikan informasi latar belakang yang menarik. Jadi saya hanya meninggalkan garis miring setelah "http (s):". Mungkin seseorang dengan reputasi yang lebih baik dapat memperbaiki tautan dan menghapus catatan ini.

Henri Hulski
sumber
Sejak Django 1.9, proyek ini tidak relevan, pengelola tidak hanya mengiklankannya, lihat code.djangoproject.com/ticket/15053 dan github.com/stephenmcd/django-overextends/pull/37 . Untuk mengambil kendali penuh dari aplikasi mana template dimuat, ada django-apptemplates dan django-app-namespace-template-loader, yang keduanya masih relevan jika Anda ingin memperluas dari satu aplikasi ke aplikasi lainnya.
benjaoming