Temel Django yönetici şablonları nasıl geçersiz kılınır ve genişletilir?


126

Bir yönetici şablonunu (ör. Admin / index.html) genişletirken aynı zamanda nasıl geçersiz kılabilirim (bkz. Https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing -an-admin-şablon )?

İlk olarak - Bu sorunun daha önce sorulduğunu ve yanıtlandığını biliyorum (bkz. Django: Bir uygulama şablonunu geçersiz kılma VE genişletme ), ancak yanıtın da dediği gibi, app_directories şablon yükleyicisini kullanıyorsanız (çoğu zaman).

Mevcut çözümüm, doğrudan yönetici şablonlarından genişletmek yerine kopyalar oluşturmak ve bunlardan genişletmek. Bu harika çalışıyor ancak gerçekten kafa karıştırıcı ve yönetici şablonları değiştiğinde fazladan iş ekliyor.

Şablonlar için bazı özel genişletme etiketleri düşünebilir, ancak zaten bir çözüm varsa tekerleği yeniden icat etmek istemiyorum.

Bir yan not: Bu sorunun Django tarafından çözülüp çözülmeyeceğini bilen var mı?


1
Yönetici şablonlarını kopyalamak, genişletmek ve blokları geçersiz kılmak / eklemek, Django'nun mevcut durumu göz önüne alındığında optimal iş akışı olmasa da en verimli olanıdır. Onunla çalıştığın üç yıldır yapmaya çalıştığın şeyi yapmanın başka bir yolunu görmedim :)
Brandon

Şey - bunun iyi bir şey olup olmadığını bilmiyorum ama en azından senin gibi insanlar aynı sonuca vardılar. Bunu duymak güzel. :)
Semmel

Yanıtlar:


101

Güncelleme :

Django sürümünüz için Dokümanları okuyun. Örneğin

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 -Şablonlar

2011 tarihli orijinal cevap:

Aynı sorunu yaklaşık bir buçuk yıl önce yaşadım ve djangosnippets.org'da bunu kolaylaştıran güzel bir şablon yükleyici buldum . Belirli bir uygulamada bir şablonu genişletmenize olanak tanıyarak size admin / index.html şablonunu yönetici uygulamasından genişleten kendi admin / index.html'nizi oluşturma olanağı verir . Bunun gibi:

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

Bu şablon yükleyicinin web sitemdeki bir blog gönderisinde nasıl kullanılacağına dair tam bir örnek verdim.


18
Referans için; söz konusu snippet bir django uygulamasına dönüştürüldü ve PyPi'de (pip / easy_install) django-apptemplates olarak mevcut: pypi.python.org/pypi/django-apptemplates
Romløk

9
Sadece% 100 açık olmak gerekirse: Yukarıdaki çözüm, komut dosyasının kullandığı işlevlerden biri amortismana tabi tutulduğundan, Django'nun son sürümleri için (en az 1.4) ARTIK ÇALIŞMAYACAKTIR. Güncellenen kaynağı burada bulabilirsiniz
OldTinfoil

2
Django 1.8 ile bunun yine de çalışacağını, ancak kurulumun özel bir şekilde yapılması gerektiğini unutmayın ( örnek olarak app_namespace.Loader kurulumuna bakın ). django-app-namespace-template-loader , django-apptemplatesbir gün çalışmayı durdurup durdurmayacağına da çalışan bir alternatiftir .
Peterino

Bu cevap, eski Django sürümleri için çok iyiydi. Ancak şu an için Cheng'in başka bir cevabı daha alakalı. stackoverflow.com/a/29997719/7344164
SoftwareEnggUmar

70

Django 1.8'in güncel sürüm olması için, yukarıdaki cevaplarda önerildiği gibi sembolik linke, yönetici / şablonları proje klasörünüze kopyalamanıza veya ara yazılımları yüklemenize gerek yoktur. İşte yapmanız gerekenler:

  1. aşağıdaki ağaç yapısını oluşturun ( resmi belgeler tarafından tavsiye edilir )

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

Not : Bu dosyanın konumu önemli değildir. Bunu uygulamanızın içine koyabilirsiniz ve çalışmaya devam edecektir. Konumu django tarafından keşfedilebildiği sürece. Daha da önemlisi, HTML dosyasının adı, django tarafından sağlanan orijinal HTML dosyası adıyla aynı olmalıdır.

  1. Bu şablon yolunu ayarlarınıza ekleyin.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. Geçersiz kılmak istediğiniz adı ve bloğu tanımlayın. Bu, django'nun admin / templates dizinine bakılarak yapılır. Virtualenv kullanıyorum, bu yüzden benim için yol burada:

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

Bu örnekte, yeni kullanıcı ekle formunu değiştirmek istiyorum. Bu görünüm için şablon sorumlusu change_form.html'dir . Change_form.html dosyasını açın ve genişletmek istediğiniz {% block%} 'u bulun.

  1. In sizin change_form.html , yazma bazı şeyleri böyle:

    {% extends "admin/change_form.html" %}
    {% block field_sets %}
         {# your modification here #}
    {% endblock %}
  2. Sayfanızı yükleyin ve değişiklikleri görmelisiniz


Tüm blokları kopyalamadan ana "index.html" şablonunu genişletmek için hala yeterli değil. Bir çözüm, bazılarını ../"exetends" yoluna yazmak ve orijinal yolu daha benzersiz belirlemektir {% extends "../../admin/templates/admin/index.html" %}. cevap için bağlantı
hynekcer

1
ŞABLONLARDA 'DIRS' kullanmamız gerektiğini düşünüyorum: [os.path.join (BASE_DIR, 'templates')],
Raul Reyes

Bu, SO'daki kusuru mükemmel bir şekilde gösteren iplik türüdür. Bir çerçeve güncellenir ve soru artık alakalı değildir, aslında doğru yoldan caydırıcıdır. Burada harika cevap. RTFM çocuklar.
Derek Adair

Bu cevap için teşekkürler. "Bu dosyanın konumu önemli değil." Dışında, her şey harika çalıştı.
Jaswanth Manigundan

54

öğesinin üzerine yazmanız gerekirse admin/index.html, .product dosyasının index_template parametresini ayarlayabilirsiniz AdminSite.

Örneğin

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

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

ve şablonunuzu yerleştirin <appname>/templates/admin/my_custom_index.html


5
Parlak! Bunu yapmak {% extends "admin/index.html" %}, my_custom_index.html'den yapmanıza ve kopyalamadan django yönetici şablonuna başvurmanıza olanak tanır . Teşekkür ederim.
mattmc3

3
Yerleşik django özelliklerini kullanan ve özel şablon yükleyicileri kullanmayı gerektirmeyen en basit yaklaşım bu olduğundan, @Semmel bunu doğru cevap olarak işaretlemelidir.
MrColes


9

Chengs'in cevabı doğru, ancak yönetici dokümanlarına göre her yönetici şablonunun üzerine bu şekilde yazılamaz: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#overriding-admin-templates

Uygulama veya model başına geçersiz kılınabilen şablonlar

Contrib / admin / templates / admin'deki her şablon uygulama veya model bazında geçersiz kılınmayabilir. Aşağıdakiler şunları yapabilir:

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

Olanlar için geçersiz kılınan olamaz şablonları bu şekilde, hala tüm proje için onları geçersiz kılabilir. Sadece yerleştirmek için yeni bir versiyon şablonları / yönetici dizininde. Bu, özellikle özel 404 ve 500 sayfaları oluşturmak için kullanışlıdır

Yöneticinin login.html dosyasının üzerine yazmak zorunda kaldım ve bu nedenle üzerine yazılan şablonu bu klasör yapısına koymak zorunda kaldım:

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

(yöneticideki myapp alt klasörü olmadan) Cheng'in gönderisine yorum yapmak için yeterli itibarım yok, bu yüzden bunu yeni cevap olarak yazmak zorunda kaldım.


Geri bildirim için teşekkürler hyneker Umarım cevabım şimdi daha net ve daha doğrudur.
matyas

Evet, şablonlardan bazıları isteğe bağlı olarak uygulama düzeyinde değiştirilebilse bile, proje düzeyinde özelleştirilebileceğini bilmekte fayda var.
hynekcer

5

Bunu yapmanın en iyi yolu, Django yönetici şablonlarını projenizin içine koymaktır. Yani templates/admin, stok Django yönetici şablonları söz konusu olduğunda şablonlarınız içeride olacaktır template/django_admin. Ardından, aşağıdaki gibi bir şey yapabilirsiniz:

templates / yönetici / change_form.html

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

Your stuff here

Stok şablonlarını güncel tutmaktan endişeleniyorsanız, bunları svn harici veya benzeri öğelerle dahil edebilirsiniz.


Svn harici kullanmak harika bir fikir. Bunun ortaya çıkardığı sorun, tüm çevirmenlerimin tüm bu şablonları çevirecek olmasıdır (çünkü makemessages tüm yönetici şablonlarından çeviri dizelerini toplayacaktır), bu da birden çok dilde çalışıyorsanız çok fazla iş ekler. Belki bu şablonları yapım mesajlarından hariç tutmanın bir yolu vardır?
Semmel

--ignoreArgümanı ile kullanın makemessages. Bakınız: docs.djangoproject.com/en/dev/ref/django-admin/#makemessages
Chris Pratt

Diğer cevabın ihtiyacıma daha çok uyduğunu düşünüyorum. Ancak çözümünüzü beğendim ve şablon yükleyicilerinizle uğraşmak istemiyorsanız bunun iyi bir alternatif olduğunu düşünüyorum.
Semmel

5

Resmi Django belgelerinde , varsayılan yönetici şablonlarını geçersiz kılmak / genişletmek için ihtiyacım olan tüm bilgileri içeren tek bir cevap veya bir bölüm bulamadım , bu yüzden bu yanıtı eksiksiz bir kılavuz olarak yazıyorum ve yardımcı olacağını umuyorum gelecekte diğerleri için.

Standart Django proje yapısını varsayarsak:

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/

İşte yapmanız gerekenler:

  1. İçinde mysite/admin.py, bir alt sınıf oluşturun 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()

    Emin ithal etmek olun custom_admin_siteiçinde admin.pyuygulamalarınızın ve (eğer isterseniz) özelleştirilmiş yönetici sitesinde görüntülemeyi üzerinde sizin modellerini kayıt olun.

  2. İse mysite/apps.py, bir alt sınıf oluşturmak AdminConfigve set default_siteiçin admin.CustomAdminSiteönceki adımdaki:

    from django.contrib.admin.apps import AdminConfig
    
    
    class CustomAdminConfig(AdminConfig):
        default_site = 'admin.CustomAdminSite'
  3. Olarak mysite/settings.pydeğiştirin django.admin.siteiçinde INSTALLED_APPSolan apps.CustomAdminConfig(önceki adımdan özel yönetici uygulaması yapılandırma).

  4. İçinde mysite/urls.py, admin.site.urlsyönetici URL'sini şu şekilde değiştirin :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. Belgelerdetemplates belirtildiği gibi varsayılan Django yönetici şablonları dizin yapısını koruyarak dizininizde değiştirmek istediğiniz şablonu oluşturun . Örneğin, değişiklik yapıyorsanız , dosyayı oluşturun .admin/index.htmltemplates/admin/index.html

    Mevcut tüm şablonlar bu şekilde değiştirilebilir ve isimleri ve yapıları Django'nun kaynak kodunda bulunabilir .

  6. Artık şablonu sıfırdan yazarak geçersiz kılabilir veya genişletebilir ve ardından belirli blokları geçersiz kılabilir / genişletebilirsiniz.

    Örneğin, her şeyi olduğu gibi tutmak, ancak contentengellemeyi geçersiz kılmak istiyorsanız (indeks sayfasında kaydettiğiniz uygulamaları ve modellerini listeler), aşağıdakileri ekleyin templates/admin/index.html:

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

    Bir bloğun orijinal içeriğini korumak için {{ block.super }}, orijinal içeriğin görüntülenmesini istediğiniz yere ekleyin :

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

    Ayrıca extrastyleve extraheadbloklarını değiştirerek özel stiller ve komut dosyaları ekleyebilirsiniz .


bununla ilgili bir kaynağınız veya belgeniz var mı?
Mary

5. maddede eklediğim iki referans dışında, hayır, başka hiçbir şeyim yok.
Faheel

1

Chris Pratt'a katılıyorum. Ancak, yönetici şablonlarının yerleştirildiği orijinal Django klasörüne symlink oluşturmanın daha iyi olacağını düşünüyorum:

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

ve görebileceğiniz gibi, python sürümüne ve Django'nun yüklendiği klasöre bağlıdır. Bu nedenle, gelecekte veya bir üretim sunucusunda yolu değiştirmeniz gerekebilir.


0

Bu site, Django 1.7 yapılandırmamla çalışan basit bir çözüme sahipti.

İLK: Projenizin şablon / dizininde kurulu Django şablonlarınıza admin_src adında bir symlink oluşturun. Bir virtualenv kullanarak Dreamhost'ta benim için, "kaynak" Django yönetici şablonlarım şöyleydi:

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

İKİNCİ: Şablonlarda bir yönetici dizini oluşturun /

Yani projemin şablon / dizini şimdi şöyle görünüyordu:

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

ÜÇÜNCÜ: Yeni şablon / admin / dizininizde bu içeriğe sahip bir base.html dosyası oluşturun :

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

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

DÖRDÜNCÜ: admin favicon-admin.ico'nuzu statik kök img klasörünüze ekleyin.

Bitti. Kolay.


0

uygulama dizini için bu satırı url.py gibi yaygın bir py dosyasına ekleyin

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

uygulama modülü dizini için: bu satırı admin.py'ye ekleyin

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

değişiklik listesi için: bu satırı yönetici sınıfına ekleyin:

change_list_template = "servers/servers_changelist.html"

uygulama modülü form şablonu için: bu satırı yönetici sınıfınıza ekleyin

change_form_template = "servers/server_changeform.html"

vb. ve aynı yöneticinin modül sınıflarında başka bul


-1

Django için dairesel şablon kalıtımı sağlayan django-overerextends'ı kullanabilirsiniz .

Stephen'ın onu bağımsız bir Django uzantısına çıkardığı Mezzanine CMS'den geliyor .

Mezzanine belgelerinde "Şablonları Geçersiz Kılma ve Genişletme" (http: /mezzanine.jupo.org/docs/content-architecture.html#overriding-vs-extending-templates) bölümünde daha fazla bilgi bulabilirsiniz.

Daha derin bilgiler için Stephens Blog "Django için Dairesel Şablon Kalıtımı" na bakın (http: /blog.jupo.org/2012/05/17/circular-template-inheritance-for-django).

Ve Google Grupları'nda bu özelliğin geliştirilmesini başlatan tartışma (https: /groups.google.com/forum / #! Topic / mezzanine-users / sUydcf_IZkQ).

Not:

2'den fazla bağlantı ekleyecek itibarım yok. Ancak bağlantıların ilginç arka plan bilgileri sağladığını düşünüyorum. Ben de "http (s):" den sonra bir bölü işareti bıraktım. Belki daha iyi itibara sahip biri bağlantıları onarabilir ve bu notu kaldırabilir.


Django 1.9'dan beri, bu proje alakalı değildi, bakımcı sadece reklamını yapmıyor , bkz. Code.djangoproject.com/ticket/15053 ve github.com/stephenmcd/django-overextends/pull/37 . Bir şablonun hangi uygulamadan yüklendiğini tam olarak kontrol etmek için, django-apptemplates ve django-app-namespace-template-loader vardır, bunlar bir uygulamadan diğerine genişletmek istiyorsanız her ikisi de hala geçerlidir.
benjaoming
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.