Làm cách nào để ghi đè và mở rộng các mẫu quản trị Django cơ bản?


126

Làm cách nào để ghi đè mẫu quản trị (ví dụ: admin / index.html) đồng thời mở rộng nó (xem https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing -an-admin-template )?

Đầu tiên - tôi biết rằng câu hỏi này đã được hỏi và trả lời trước đây (xem Django: Ghi đè VÀ mở rộng mẫu ứng dụng ) nhưng như câu trả lời cho biết nó không áp dụng trực tiếp nếu bạn đang sử dụng trình tải mẫu app_directories (phần lớn thời gian).

Cách giải quyết hiện tại của tôi là tạo bản sao và mở rộng từ chúng thay vì mở rộng trực tiếp từ các mẫu quản trị. Điều này hoạt động tốt nhưng nó thực sự khó hiểu và thêm công việc khi các mẫu quản trị viên thay đổi.

Nó có thể nghĩ về một số thẻ mở rộng tùy chỉnh cho các mẫu nhưng tôi không muốn phát minh lại bánh xe nếu đã có giải pháp.

Một lưu ý nhỏ: Có ai biết liệu vấn đề này có được giải quyết bởi chính Django không?


1
Sao chép các mẫu quản trị, mở rộng chúng và ghi đè / thêm khối là hiệu quả nhất, mặc dù quy trình làm việc không tối ưu với trạng thái hiện tại của Django. Tôi chưa thấy bất kỳ cách nào khác để làm những gì bạn đang cố gắng để làm trong ba năm làm việc với nó :)
Brandon

Chà - tôi không biết đây có phải là một điều tốt hay không nhưng ít nhất những người như bạn đã đi đến kết luận tương tự. Thật tốt khi nghe. :)
Semmel

Câu trả lời:


101

Cập nhật :

Đọc Tài liệu cho phiên bản Django của bạn. ví dụ

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 -mẫu

Câu trả lời gốc từ năm 2011:

Tôi đã gặp vấn đề tương tự cách đây khoảng một năm rưỡi và tôi đã tìm thấy một trình tải mẫu đẹp trên djangosnippets.org giúp việc này trở nên dễ dàng. Nó cho phép bạn mở rộng mẫu trong một ứng dụng cụ thể, cung cấp cho bạn khả năng tạo admin / index.html của riêng bạn để mở rộng mẫu admin / index.html từ ứng dụng quản trị. Như thế này:

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

Tôi đã đưa ra một ví dụ đầy đủ về cách sử dụng trình tải mẫu này trong một bài đăng blog trên trang web của tôi.


18
Để tham khảo; đoạn trong câu hỏi đã được chuyển đổi sang một ứng dụng django, và có sẵn trong PyPi (pip / easy_install) như django-apptemplates: pypi.python.org/pypi/django-apptemplates
Romløk

9
Chỉ rõ ràng 100%: giải pháp ở trên SẼ KHÔNG CÒN HIỆU QUẢ cho các phiên bản gần đây của Django (ít nhất là 1.4), vì một trong những chức năng mà tập lệnh sử dụng bị mất giá trị. Bạn có thể tìm thấy nguồn cập nhật trên đây
OldTinfoil

2
Lưu ý rằng với Django 1.8, điều này sẽ vẫn hoạt động, nhưng thiết lập cần được thực hiện theo một cách đặc biệt (xem thiết lập app_namespace.Loader làm ví dụ). django-app-namespace-template-loader cũng là một giải pháp thay thế hoạt động django-apptemplatesnếu một ngày nào đó nó có thể ngừng hoạt động.
Peterino

Câu trả lời này rất tốt cho các phiên bản Django cũ hơn. Nhưng hiện tại, một câu trả lời khác của Cheng có liên quan hơn. stackoverflow.com/a/29997719/7344164
SoftwareEnggUmar

70

Đối với Django 1.8 là bản phát hành hiện tại, không cần phải liên kết biểu tượng, sao chép quản trị / mẫu vào thư mục dự án của bạn hoặc cài đặt phần mềm trung gian theo gợi ý của các câu trả lời ở trên. Dưới đây là những gì để làm:

  1. tạo cấu trúc cây sau (được khuyến nghị bởi tài liệu chính thức )

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

Lưu ý : Vị trí của tệp này không quan trọng. Bạn có thể đặt nó bên trong ứng dụng của mình và nó sẽ vẫn hoạt động. Miễn là vị trí của nó có thể được phát hiện bởi django. Điều quan trọng hơn là tên của tệp HTML phải giống với tên tệp HTML gốc do django cung cấp.

  1. Thêm đường dẫn mẫu này vào settings của bạn.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. Xác định tên và khối bạn muốn ghi đè. Điều này được thực hiện bằng cách nhìn vào thư mục quản trị / mẫu của django. Tôi đang sử dụng virtualenv, vì vậy đối với tôi, đường dẫn là ở đây:

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

Trong ví dụ này, tôi muốn sửa đổi biểu mẫu thêm người dùng mới. Phản hồi mẫu cho chế độ xem này là change_form.html . Mở change_form.html và tìm {% block%} mà bạn muốn mở rộng.

  1. Trong change_form.html của bạn , hãy viết những thứ như sau:

    {% extends "admin/change_form.html" %}
    {% block field_sets %}
         {# your modification here #}
    {% endblock %}
  2. Tải lên trang của bạn và bạn sẽ thấy những thay đổi


Nó vẫn không đủ để mở rộng mẫu "index.html" chính mà không sao chép tất cả các khối. Một giải pháp là viết một số ../vào đường dẫn "exetends" và chỉ định đường dẫn ban đầu độc đáo hơn {% extends "../../admin/templates/admin/index.html" %}. liên kết đến câu trả lời
hynekcer

1
Tôi nghĩ trong TEMPLATES, chúng ta nên sử dụng 'DIRS': [os.path.join (BASE_DIR, 'templates')],
Raul Reyes

Đây là loại chủ đề minh họa hoàn hảo lỗ hổng trong SO. Một khuôn khổ được cập nhật và câu hỏi không còn phù hợp nữa, nó thực chất là một yếu tố cản trở con đường thích hợp. Câu trả lời tuyệt vời ở đây. RTFM trẻ em.
Derek Adair

Cảm ơn vì câu trả lời này. Ngoại trừ "Vị trí của tệp này không quan trọng.", Mọi thứ đều hoạt động tốt.
Jaswanth Manigundan

54

nếu bạn cần ghi đè admin/index.html, bạn có thể đặt tham số index_template của AdminSite.

ví dụ

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

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

và đặt mẫu của bạn vào <appname>/templates/admin/my_custom_index.html


5
Xuất sắc! Làm điều này cho phép bạn sau đó thực hiện {% extends "admin/index.html" %}từ my_custom_index.html và có tham chiếu đó đến mẫu quản trị django mà không cần sao chép nó. Cảm ơn bạn.
mattmc3

3
@Semmel nên đánh dấu đây là câu trả lời chính xác, vì đây là cách tiếp cận đơn giản nhất sử dụng các tính năng django tích hợp sẵn và không yêu cầu sử dụng trình tải mẫu tùy chỉnh.
MrColes

17

Với django1,5 (ít nhất), bạn có thể xác định mẫu bạn muốn sử dụng cho mộtmodeladmin

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

Bạn có thể làm một cái gì đó như

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

Với change_form.htmlviệc là một mẫu html đơn giản mở rộng admin/change_form.html(hoặc không nếu bạn muốn làm điều đó từ đầu)


9

Câu trả lời của Chengs là đúng, theo tài liệu quản trị viên, không phải mọi mẫu quản trị viên đều có thể bị ghi đè theo cách này: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#overriding-admin-templates

Các mẫu có thể bị ghi đè trên mỗi ứng dụng hoặc kiểu máy

Không phải mọi mẫu trong đóng góp / quản trị / mẫu / quản trị viên đều có thể bị ghi đè trên mỗi ứng dụng hoặc mỗi mô hình. Sau đây có thể:

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

Đối với những mẫu không thể được ghi đè theo cách này, bạn vẫn có thể ghi đè chúng cho toàn bộ dự án của mình. Chỉ cần đặt phiên bản mới vào thư mục mẫu / quản trị viên của bạn . Điều này đặc biệt hữu ích để tạo các trang 404 và 500 tùy chỉnh

Tôi đã phải ghi đè login.html của quản trị viên và do đó phải đặt mẫu ghi đè vào cấu trúc thư mục này:

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

(không có thư mục con myapp trong quản trị viên) Tôi không có đủ thận trọng khi nhận xét về bài đăng của Cheng, đây là lý do tại sao tôi phải viết câu trả lời này như là câu trả lời mới.


Cảm ơn bạn đã phản hồi hyneker Tôi hy vọng câu trả lời của tôi rõ ràng hơn và đi thẳng vào vấn đề bây giờ.
matyas,

Vâng, sẽ rất hữu ích khi biết rằng các mẫu có thể được tùy chỉnh ở cấp độ dự án ngay cả khi một số mẫu có thể được thay đổi tùy ý ở cấp ứng dụng.
hynekcer

5

Cách tốt nhất để làm điều đó là đặt các mẫu quản trị Django bên trong dự án của bạn. Vì vậy, các mẫu của bạn sẽ ở trong templates/adminkhi các mẫu quản trị Django có sẵn sẽ được nói template/django_admin. Sau đó, bạn có thể làm như sau:

Template / admin / change_form.html

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

Your stuff here

Nếu bạn lo lắng về việc giữ cho các mẫu kho được cập nhật, bạn có thể bao gồm chúng với các thiết bị ngoại vi svn hoặc tương tự.


Sử dụng bên ngoài svn là một ý tưởng tuyệt vời. Vấn đề mà điều này giới thiệu là tất cả các dịch giả của tôi sẽ dịch tất cả các mẫu đó (vì makemessages sẽ thu thập các chuỗi dịch từ tất cả các mẫu quản trị), điều này sẽ bổ sung thêm rất nhiều công việc nếu bạn đang làm việc với nhiều ngôn ngữ. Có thể có một cách để loại trừ những mẫu đó khỏi trang điểm?
Semmel

Sử dụng --ignoređối số với makemessages. Xem: docs.djangoproject.com/en/dev/ref/django-admin/#makemessages
Chris Pratt

Tôi nghĩ câu trả lời kia phù hợp với nhu cầu của tôi hơn. Nhưng tôi thích giải pháp của bạn và nghĩ rằng đó là một giải pháp thay thế tốt nếu bạn không muốn gặp rắc rối với bộ tải mẫu của mình.
Semmel

5

Tôi không thể tìm thấy một câu trả lời hoặc một phần trong tài liệu Django chính thức có tất cả thông tin tôi cần để ghi đè / mở rộng các mẫu quản trị viên mặc định, vì vậy tôi viết câu trả lời này như một hướng dẫn đầy đủ, hy vọng rằng nó sẽ hữu ích cho những người khác trong tương lai.

Giả sử cấu trúc dự án Django tiêu chuẩn:

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/

Đây là những gì bạn cần làm:

  1. Trong mysite/admin.py, tạo một lớp con của 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()

    Đảm bảo nhập custom_admin_sitevào các admin.pyứng dụng của bạn và đăng ký các mô hình của bạn trên đó để hiển thị chúng trên trang web quản trị tùy chỉnh của bạn (nếu bạn muốn).

  2. Trong mysite/apps.py, tạo một lớp con của AdminConfigvà đặt default_sitethành admin.CustomAdminSitetừ bước trước:

    from django.contrib.admin.apps import AdminConfig
    
    
    class CustomAdminConfig(AdminConfig):
        default_site = 'admin.CustomAdminSite'
  3. Trong mysite/settings.py, thay thế django.admin.sitetrong INSTALLED_APPSvới apps.CustomAdminConfig(tùy chỉnh quản trị ứng dụng cấu hình của bạn từ bước trước).

  4. Trong mysite/urls.py, thay thế admin.site.urlstừ URL quản trị thànhcustom_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. Tạo mẫu bạn muốn sửa đổi trong templatesthư mục của mình , duy trì cấu trúc thư mục mẫu quản trị Django mặc định như được chỉ định trong tài liệu . Ví dụ: nếu bạn đang sửa đổi admin/index.html, hãy tạo tệp templates/admin/index.html.

    Tất cả các mẫu hiện có có thể được sửa đổi theo cách này, tên và cấu trúc của chúng có thể được tìm thấy trong mã nguồn của Django .

  6. Bây giờ bạn có thể ghi đè mẫu bằng cách viết nó từ đầu hoặc mở rộng nó và sau đó ghi đè / mở rộng các khối cụ thể.

    Ví dụ: nếu bạn muốn giữ nguyên mọi thứ nhưng muốn ghi đè lên contentkhối (trên trang chỉ mục liệt kê các ứng dụng và kiểu máy mà bạn đã đăng ký), hãy thêm phần sau vào templates/admin/index.html:

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

    Để bảo toàn nội dung ban đầu của một khối, hãy thêm {{ block.super }}bất cứ nơi nào bạn muốn nội dung gốc được hiển thị:

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

    Bạn cũng có thể thêm các kiểu và tập lệnh tùy chỉnh bằng cách sửa đổi các khối extrastyleextrahead.


bạn có một nguồn hoặc tài liệu về điều này?
Mary

Ngoài hai tài liệu tham khảo tôi đã thêm ở điểm 5, không, tôi không có bất cứ thứ gì khác.
Faheel

1

Tôi đồng ý với Chris Pratt. Nhưng tôi nghĩ tốt hơn nên tạo liên kết tượng trưng vào thư mục Django gốc, nơi các mẫu quản trị viên đặt trong:

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

và như bạn có thể thấy, nó phụ thuộc vào phiên bản python và thư mục nơi Django được cài đặt. Vì vậy, trong tương lai hoặc trên máy chủ sản xuất, bạn có thể cần thay đổi đường dẫn.


0

Trang web này có một giải pháp đơn giản hoạt động với cấu hình Django 1.7 của tôi.

ĐẦU TIÊN: Tạo một liên kết tượng trưng có tên admin_src trong thư mục / mẫu của dự án tới các mẫu Django đã cài đặt của bạn. Đối với tôi trên Dreamhost sử dụng virtualenv, các mẫu quản trị Django "nguồn" của tôi ở trong:

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

THỨ HAI: Tạo quản trị viên thư mục trong các mẫu /

Vì vậy, mẫu / thư mục dự án của tôi bây giờ trông như thế này:

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

THỨ BA: Trong thư mục template / admin / mới của bạn, hãy tạo một tệp base.html với nội dung sau:

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

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

THỨ 4: Thêm favicon-admin.ico quản trị viên của bạn vào thư mục img gốc tĩnh của bạn.

Làm xong. Dễ dàng.


0

đối với chỉ mục ứng dụng, hãy thêm dòng này vào một nơi nào đó tệp py phổ biến như url.py

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

cho chỉ mục mô-đun ứng dụng: thêm dòng này vào admin.py

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

cho danh sách thay đổi: thêm dòng này vào lớp quản trị:

change_list_template = "servers/servers_changelist.html"

cho mẫu biểu mẫu mô-đun ứng dụng: thêm dòng này vào lớp quản trị của bạn

change_form_template = "servers/server_changeform.html"

v.v. và tìm những người khác trong cùng các lớp mô-đun của quản trị viên


-1

Bạn có thể sử dụng django-overextends , cung cấp tính năng kế thừa mẫu hình tròn cho Django.

Nó đến từ CMS Mezzanine , từ đó Stephen đã trích xuất nó thành một tiện ích mở rộng Django độc lập.

Bạn tìm thấy nhiều thông tin hơn trong "Ghi đè so với mở rộng mẫu" (http: /mezzanine.jupo.org/docs/content-architecture.html#overriding-vs-exfining-templates) bên trong tài liệu Mezzanine.

Để biết thêm thông tin chi tiết, hãy xem Blog Stephens "Kế thừa Mẫu Thông tư cho Django" (http: /blog.jupo.org/2012/05/17/circular-template-inheritance-for-django).

Và trong Google Groups, cuộc thảo luận (https: /groups.google.com/forum / #! Topic / lửng-người-dùng / sUydcf_IZkQ) đã bắt đầu phát triển tính năng này.

Ghi chú:

Tôi không có danh tiếng để thêm nhiều hơn 2 liên kết. Nhưng tôi nghĩ rằng các liên kết cung cấp thông tin cơ bản thú vị. Vì vậy, tôi chỉ bỏ đi một dấu gạch chéo sau "http (s):". Có thể ai đó có danh tiếng tốt hơn có thể sửa chữa các liên kết và xóa ghi chú này.


Kể từ Django 1.9, dự án này không có liên quan, người bảo trì chỉ không quảng cáo nó, hãy xem code.djangoproject.com/ticket/15053github.com/stephenmcd/django-overextends/pull/37 . Để kiểm soát hoàn toàn ứng dụng mà mẫu được tải, có django-apptemplates và django-app-namespace-template-loader, cả hai vẫn có liên quan nếu bạn muốn mở rộng từ ứng dụng này sang ứng dụng khác.
benjaoming
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.