mẫu django: bao gồm và mở rộng


108

Tôi muốn cung cấp cùng một nội dung bên trong 2 tệp cơ sở khác nhau.

Vì vậy, tôi đang cố gắng làm điều này:

page1.html:

{% extends "base1.html" %}
{% include "commondata.html" %}

trang2.html:

{% extends "base2.html" %} 
{% include "commondata.html" %}

Vấn đề là tôi dường như không thể sử dụng cả mở rộng và bao gồm. Có một số cách để làm điều đó? Và nếu không, làm thế nào tôi có thể thực hiện được những điều trên?

commondata.html ghi đè một khối được chỉ định trong cả base1.html và base2.html

Mục đích của việc này là cung cấp cùng một trang ở cả định dạng pdf và html, trong đó định dạng hơi khác nhau. Câu hỏi trên mặc dù đơn giản hóa những gì tôi đang cố gắng làm như vậy nếu tôi có thể nhận được câu trả lời rằng nó sẽ giải quyết được vấn đề của tôi.

Câu trả lời:


110

Khi bạn sử dụng thẻ mẫu mở rộng, bạn đang nói rằng mẫu hiện tại mở rộng một mẫu khác - đó là mẫu con, phụ thuộc vào mẫu mẹ. Django sẽ xem xét mẫu con của bạn và sử dụng nội dung của mẫu đó để điền mẫu mẹ.

Mọi thứ bạn muốn sử dụng trong mẫu con phải nằm trong các khối, mà Django sử dụng để điền vào mẫu chính. Nếu bạn muốn sử dụng một câu lệnh include trong mẫu con đó, bạn phải đặt nó trong một khối để Django hiểu được điều đó. Nếu không thì nó chẳng có ý nghĩa gì và Django không biết phải làm gì với nó.

Tài liệu Django có một vài ví dụ thực sự tốt về việc sử dụng các khối để thay thế các khối trong mẫu mẹ.

https://docs.djangoproject.com/en/dev/ref/templates/language/#template-inheritance


1
commondata.html của tôi có khối được xác định trong đó. Nhưng nó không thay thế khối tempalte mẹ ... Nếu thay vì thực hiện bao gồm, tôi viết dữ liệu chính xác hai lần trong cả page1.html và page2.html thì tất nhiên nó hoạt động. Nhưng tôi muốn tính điểm chung đó vào commondata.html.
Net Citizen

Có vẻ hiệu quả, tôi nhớ đã thử cái này nhưng chắc chắn lúc đó tôi đã mắc lỗi đánh máy hoặc cái gì đó khiến nó không hoạt động.
Net Citizen,

1
xem câu trả lời của tôi bên dưới để biết tại sao nó không hoạt động với tôi lần đầu tiên, tôi sẽ để lại cho bạn câu trả lời được chấp nhận vì bạn đã trả lời đúng câu hỏi tôi hỏi.
Net Citizen

80

Từ tài liệu Django:

Thẻ include nên được coi là cách triển khai "hiển thị phương thức con này và bao gồm HTML", không phải là "phân tích cú pháp phương thức con này và bao gồm nội dung của nó như thể nó là một phần của phương thức chính". Điều này có nghĩa là không có trạng thái chia sẻ giữa các mẫu được bao gồm - mỗi mẫu bao gồm là một quá trình kết xuất hoàn toàn độc lập.

Vì vậy, Django không lấy bất kỳ khối nào từ commondata.html của bạn và nó không biết phải làm gì với các khối bên ngoài html được kết xuất.


32

Điều này sẽ thực hiện mẹo cho bạn: đặt thẻ include bên trong phần khối.

page1.html:

{% extends "base1.html" %}

{% block foo %}
   {% include "commondata.html" %}
{% endblock %}

trang2.html:

{% extends "base2.html" %}

{% block bar %}
   {% include "commondata.html" %}
{% endblock %}

1
Hoàn hảo. Làm việc cho tôi.
Trupti M Panchal

13

Thông tin thêm về lý do tại sao nó không hoạt động với tôi trong trường hợp nó giúp ích cho những người trong tương lai:

Lý do tại sao nó không hoạt động là {% include%} trong django không thích các ký tự đặc biệt như dấu nháy đơn ưa thích. Dữ liệu mẫu mà tôi đang cố đưa vào đã được dán từ word. Tôi đã phải xóa thủ công tất cả các ký tự đặc biệt này và sau đó nó đã bao gồm thành công.


3

Bạn không thể kéo các khối từ một tệp được bao gồm vào một mẫu con để ghi đè các khối của mẫu mẹ. Tuy nhiên, bạn có thể chỉ định cha mẹ trong một biến và có mẫu cơ sở được chỉ định trong ngữ cảnh.

Từ tài liệu :

{% mở rộng biến%} sử dụng giá trị của biến. Nếu biến đánh giá thành một chuỗi, Django sẽ sử dụng chuỗi đó làm tên của mẫu mẹ. Nếu biến đánh giá thành đối tượng Mẫu, Django sẽ sử dụng đối tượng đó làm mẫu mẹ.

Thay vì "page1.html" và "page2.html" riêng biệt, hãy đặt {% extends base_template %}ở đầu "commondata.html". Và sau đó trong chế độ xem của bạn, hãy xác định base_templatelà "base1.html" hoặc "base2.html".


2

Được thêm để tham khảo cho những người trong tương lai tìm thấy thông tin này qua google: Bạn có thể muốn xem thẻ {% overextend%} do thư viện lửng cung cấp cho các trường hợp như thế này.


1

Chỉnh sửa ngày 10 tháng 12 năm 2015 : Như đã chỉ ra trong các nhận xét, ssi không được dùng nữa kể từ phiên bản 1.8. Theo tài liệu:

Thẻ này không được dùng nữa và sẽ bị xóa trong Django 1.10. Sử dụng thẻ bao gồm thay thế.


Theo tôi, câu trả lời đúng (tốt nhất) cho câu hỏi này là câu trả lời từ podshumok , vì nó giải thích tại sao hành vi của include khi được sử dụng cùng với kế thừa.

Tuy nhiên, tôi hơi ngạc nhiên khi không ai đề cập đến thẻ ssi được cung cấp bởi hệ thống tạo khuôn mẫu Django, được thiết kế đặc biệt cho nội tuyến bao gồm một đoạn văn bản bên ngoài . Ở đây, nội tuyến có nghĩa là văn bản bên ngoài sẽ không được diễn giải, phân tích cú pháp hoặc nội suy, mà chỉ đơn giản là được "sao chép" bên trong mẫu gọi.

Vui lòng tham khảo tài liệu để biết thêm chi tiết (hãy nhớ kiểm tra phiên bản Django thích hợp của bạn trong bộ chọn ở phần dưới bên phải của trang).

https://docs.djangoproject.com/en/dev/ref/templates/builtins/#ssi

Từ tài liệu:

ssi
Outputs the contents of a given file into the page.
Like a simple include tag, {% ssi %} includes the contents of another file
 which must be specified using an absolute path  in the current page

Cũng cần lưu ý đến các tác động bảo mật của kỹ thuật này và cũng như định nghĩa ALLOWED_INCLUDE_ROOTS bắt buộc, phải được thêm vào tệp cài đặt của bạn.


1
Lưu ý, kể từ ngày 1.8, ssi đã không được chấp nhận nữa để chuyển sang tính năng Bao gồm. https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#std:templatetag-include
Tim S.
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.