एक django टेम्पलेट में "ब्लॉक" कैसे दोहराएं


126

मैं एक ही django टेम्पलेट में दो बार समान {% ब्लॉक%} का उपयोग करना चाहता हूं । मैं चाहता हूं कि यह ब्लॉक मेरे आधार टेम्पलेट में एक से अधिक बार दिखाई दे:

# base.html
<html>
    <head>
        <title>{% block title %}My Cool Website{% endblock %}</title>
    </head>
    <body>
        <h1>{% block title %}My Cool Website{% endblock %}</h1>
    </body>
</html>

और फिर इसे बढ़ाएं:

# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}

# pictures.html
{% extends 'base.html' %}
{% block title %}My Pictures{% endblock %}

# cats.html
{% extends 'base.html' %}
{% block title %}My Cats{% endblock %}

मुझे एक अपवाद मिलेगा, क्योंकि Django चाहता है कि ब्लॉक केवल एक बार दिखाई दे:

TemplateSyntaxError पर /

'शीर्षक' टैग के साथ 'ब्लॉक' टैग एक से अधिक बार दिखाई देता है

एक त्वरित और गंदा समाधान शीर्षक 1 और title2 में ब्लॉक शीर्षक की नकल करेगा :

# blog.html
{% extends 'base.html' %}
{% block title1 %}My Blog{% endblock %}
{% block title2 %}My Blog{% endblock %}

लेकिन यह DRY सिद्धांत का उल्लंघन है । यह बहुत मुश्किल होगा क्योंकि मेरे पास बहुत सारे विरासत वाले टेम्पलेट हैं, और इसलिए भी कि मैं नरक में नहीं जाना चाहता; ;-)

इस समस्या के लिए कोई चाल या काम है? मैं सभी कोड की नकल किए बिना, अपने टेम्पलेट में उसी ब्लॉक को कैसे दोहरा सकता हूं?


1
इस सवाल का हल भी देखें stackoverflow.com/q/1178743/168034
phunehehe

2
देखें विशेष रूप से इस उत्तर के लिए प्रश्न phunehehe लिंक करता है।
तोबू

जवाबों:


69

मुझे लगता है कि संदर्भ प्रोसेसर का उपयोग इस मामले में एक ओवरकिल है। आप आसानी से ऐसा कर सकते हैं:

#base.html
<html>
    <head>
        <title>{% block title %}My Cool Website{% endblock %}</title>
    </head>
    <body>
        {% block content %}{% endblock %}
    </body>
</html>

और फिर:

# blog.html
{% extends 'base.html' %}
{% block content %}
    <h1>{% block title %}My Blog{% endblock %}</h1>
    Lorem ipsum here...
{% endblock %}

और इसी तरह ... डीआरवाई-संगत जैसा दिखता है।


1
मैं कल यह कोशिश कर सकता हूं - मैं सोच रहा था कि कैसे टेम्पलेट में दोहराव को बचाया जाए और यह एक अच्छे दृष्टिकोण की तरह लगता है। धन्यवाद।
thebiglife

1
यह दृष्टिकोण उत्कृष्ट है। मैंने अपना बेस.html को base.html और superbase.html में विभाजित कर दिया है, इसलिए यह तब भी काम करता है जब आप अपने साझा टेम्प्लेट में एक मानक शीर्षक मार्कअप (जैसे h1) रखना चाहते थे। पृष्ठ अभी भी शीर्षक ब्लॉक की सामग्री को ओवरराइड कर सकते हैं और यह दोनों स्थानों में अपडेट करेगा।
SystemParadox

2
यह पाठ को दो बार से अधिक उपयोग करने की अनुमति नहीं देता है, क्या यह करता है?
डेनिस गोलोमेज़ोव

1
डेनिस गोलोमेज़ोव: नहीं। इस मामले में, मैक्रो प्लगइन का उपयोग करना बेहतर है (नीचे देखें)।
ddd

1
अन्य तरीके से भी लागू किया जा सकता है: h1ब्लॉक के अंदर की सामग्री को परिभाषित करता है जो परिभाषित करता है title। या एक ब्लॉक जो के एक हिस्से को परिभाषित करता है title
मिकेल लिंडलॉफ

83

Django टेम्पलेट मैक्रोज़ प्लगइन का उपयोग करें:

https://gist.github.com/1715202 (django> = 1.4)

या

http://www.djangosnippets.org/snippets/363/ (django <1.4)

django> = 1.4

# base.html
{% kwacro title %}
    {% block title %}My Cool Website{% endblock %}
{% endkwacro %}

<html>
    <head>
        <title>{% usekwacro title %}</title>
    </head>
    <body>
        <h1>{% usekwacro title %}</h1>
    </body>
</html>

तथा

# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}

django <1.4

# base.html
{% macro title %}
    {% block title %}My Cool Website{% endblock %}
{% endmacro %}

<html>
    <head>
        <title>{% usemacro title %}</title>
    </head>
    <body>
        <h1>{% usemacro title %}</h1>
    </body>
</html>

तथा

# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}

2
यह शानदार है! यह वास्तव में django loops और ajax डेटा लूप्स के साथ टेम्पलेट साझा करने में मेरे द्वारा प्राप्त समस्याओं को साफ कर सकता है।
ग्लिसरीन

1
अच्छा समाधान। हालाँकि, यह "यूज़_मैक्रो" है। "usemacro" गलत है।
Ramtin

डिफ़ॉल्ट रूप से निश्चित रूप से Django में बनाया जाना चाहिए।
zepp.lee

19

आप शायद वास्तव में एक ब्लॉक का उपयोग नहीं करना चाहते हैं, बल्कि केवल एक चर का उपयोग करना चाहते हैं:

# base.html
<html>
    <head>
        <title>{{ title|default:"My Cool Website" }}</title>
    </head>
    <body>
        <h1>{{ title|default:"My Cool Website" }}</h1>
    </body>
</html>

आपने तब संदर्भ के माध्यम से शीर्षक निर्धारित किया है।


17
शायद सूखी। लेकिन आप शीर्षक को दृश्य के भीतर सेट नहीं करना चाहेंगे; लेकिन टेम्पलेट्स में।
लक्ष्मण प्रसाद

6
टाइटल को टेम्प्लेट के भीतर से सेट किया जाना चाहिए, संदर्भ द्वारा प्रदान नहीं किया जाना चाहिए, आपको इस "शीर्षक" वेरिएबल को परिभाषित करने का एक तरीका होना चाहिए, अन्यथा यह एक अच्छा समाधान नहीं है।
गिलाउम एस्केविन सेप

यही django admin टेम्प्लेट ({{title}} के लिए) करता है, लेकिन एक हटाने पर शीर्षक को परिभाषित करना असुविधाजनक है।
तोबू

13

यहाँ एक तरीका है जो मैंने खुद ही पता लगाने की कोशिश की:

# base_helper.html
<html>
    <head>
        <title>{% block _title1 %}{% endblock %}</title>
    </head>
    <body>
        <h1>{% block _title2 %}{% endblock %}</h1>
    </body>
</html>


# base.html
{% extends "base_helper.html" %}

# Copy title into _title1 & _title2, using "My Cool Website" as a default.
{% block _title1 %}{% block _title2 %}{% block title %}My Cool Website{% endblock %}{% endblock %}{% endblock %}

दुर्भाग्य से एक अतिरिक्त फ़ाइल की आवश्यकता होती है, लेकिन आपको शीर्षक को दृश्य से पास करने की आवश्यकता नहीं है।


अंत में मैं {% मैक्रो%} समाधान के लिए बस गया, जिसे एक नई फ़ाइल की आवश्यकता नहीं है, और कुल मिलाकर मुझे वही व्यक्त करने देता है जो मैं व्यक्त करना चाहता हूं।
रोमन स्टार्कोव

उपमा और कुशल। @dqd के उत्तर के विपरीत, ब्लॉक को नेस्टेड होने की आवश्यकता नहीं है, उदाहरण के लिए फेसबुक ओग और टैग के लिए बहुत उपयोगी है, जिसमें अन्य हेड विशेषताओं के समान सामग्री हो सकती है। वोट दें!
बेंज़कजी

2
बहुत बढ़िया जवाब। ऐसा लगता है कि DRYer @ dqd के उत्तर से भी अधिक महत्वपूर्ण है क्योंकि आपके पास प्रत्येक टेम्पलेट में <h1> टैग को दोहराना नहीं है जो कि आधार है। यह स्वीकृत उत्तर हो सकता है।
अनुपम

अति उत्कृष्ट! मैंने इसे अधिक जटिल परिदृश्यों में उपयोग किया है जहां मैं एक तालिका के पाद लेख पंक्ति को शीर्ष पर दोहराना चाहता था। और <tr>पंक्ति बल्कि जटिल थी।
कैरम

12

आप {% include subtemplate.html %}एक से अधिक बार उपयोग कर सकते हैं । यह ब्लॉक के रूप में ही नहीं है, लेकिन चाल है।


यह एक ही समस्या है। आधार टेम्प्लेट को पता नहीं होगा कि कौन सी सबटेम्पलेट में शामिल है।
वैन गेल

कृपया ध्यान दें कि includeकी तुलना में धीमी है blockdocs.djangoproject.com/en/1.10/topics/performance/…
Wtower

5

यहाँ कुछ चर्चाएँ हैं: http://code.djangoproject.com/ticket/4529 जाहिर तौर पर django कोर टीम इस टिकट को अस्वीकार कर देती है क्योंकि उन्हें लगता है कि यह एक आम इस्तेमाल नहीं किया गया परिदृश्य है, हालाँकि मैं असहमत हूँ।

इसके लिए रिपीट ब्लॉक सरल और स्वच्छ कार्यान्वयन है: https://github.com/SmileyChris/django-repeateat

टेम्पलेट मैक्रोज़ एक और है, हालांकि लेखक ने उल्लेख किया है कि यह सावधानीपूर्वक परीक्षण नहीं किया गया है: http://www.djangosnippets.org/snippets/363/

मैंने रिपीटब्लॉक का इस्तेमाल किया।


4
मूल django-repeatblock रिपॉजिटरी को हटा दिया गया लगता है। इसका सबसे अच्छा कांटा github.com/phretor/django-repeatblock लगता है ; मुझे github.com/ydm/django-sameas भी मिला , जिसे 'वॉन्टफिक्स' Django पैच की आवश्यकता नहीं है।
natevw 21

4

इस पर आने वाले किसी भी व्यक्ति के लिए एक अपडेट के रूप में, मैंने ऊपर उल्लेखित स्निपेट को लिया है और इसे टेम्प्लेट टैग लाइब्रेरी, django-macros में बदल दिया है, मैक्रोज़ को अधिक शक्तिशाली बनाता है और एक दोहराया ब्लॉक पैटर्न को स्पष्ट रूप से लागू करता है: django-macros


4

यहाँ ऊपर do_setऔर do_getटेम्पलेट टैग उत्तर के समान एक हल्का समाधान है । Django आपको संपूर्ण टेम्प्लेट संदर्भ को एक टैग में पारित करने की अनुमति देता है जो आपको एक वैश्विक चर को परिभाषित करने की अनुमति दे सकता है।

base.html:

<!DOCTYPE html>
<html lang="en">
<head>
  {% block head %}
    <title>{{ title }}</title>
  {% endblock %}
</head>
<body>
  <h1>{{ title }}</h1>
</body>
</html>

page.html:

{% extends "base.html" %}

{% block head %}
  {% define 'title' 'Homepage | title' %}
  {{ block.super }}
{% endblock %}

कस्टम टैग (यहां विचार प्राप्त हुआ: https://stackoverflow.com/a/33564990/2747924 ):

@register.simple_tag(takes_context=True)
def define(context, key, value):
    context.dicts[0][key] = value
    return ''

{% load %}अपने कस्टम टैग को भी न भूलें या उन्हें टेम्पलेट विकल्प बिलिंस सूची में जोड़ें ताकि आपको उन्हें हर टेम्पलेट में लोड न करना पड़े। इस दृष्टिकोण की एकमात्र सीमा {% define %}ब्लॉक टैग के भीतर से कॉल की जानी है क्योंकि चाइल्ड टेम्प्लेट केवल ब्लॉक टैग प्रदान करते हैं जो मूल टैग से मेल खाते हैं। यकीन नहीं होता कि अगर वहाँ एक रास्ता है। defineस्पष्ट रूप से उपयोग करने का प्रयास करने से पहले कॉल ज़रूर करें।


3

वान गेल के सुझाव पर बिल्डिंग, आप अपनी templatetags.py फ़ाइल में निम्न जोड़कर टैग प्राप्त कर सकते हैं और सेट कर सकते हैं:

register = template.Library()

Stateful = {}
def do_set(parser, token):
    _, key = token.split_contents()
    nodelist = parser.parse(('endset',))
    parser.delete_first_token()  # from the example -- why?
    return SetStatefulNode(key,nodelist)

class SetStatefulNode(template.Node):
    def __init__(self, key, nodes):
        Stateful[key] = nodes
    def render(self, context):
        return ''
register.tag('set', do_set)

def do_get(parser, token):
    tag_name, key = token.split_contents()
    return GetStatefulNode(key)

class GetStatefulNode(template.Node):
    def __init__(self, key):
       self.key = key
    def render(self, context):
        return ''.join( [x.render(context) for x in Stateful[self.key]] )

register.tag('get', do_get)

फिर एक टेम्पलेट के माध्यम से मान सेट करें {% set foo %}put data here{% endset %}और उन्हें {% get foo %}दूसरे में प्राप्त करें ।


मुझे लगता है कि सभी का सबसे सुरुचिपूर्ण समाधान है। धन्यवाद किरन और वान गेल!
रॉबर्ट लैक्रोस

यह बहुत चालाक है, लेकिन ऐसा लगता है कि सेट टैग में सभी नोड्स को रेंडर करना और भी बेहतर हो सकता है, अन्यथा वे गेट द्वारा बार-बार प्रदान किए जाते हैं। मैं उन कारणों के बारे में सोच सकता हूं जो एक अच्छा विचार हो सकता है (एक पृष्ठ पर विभिन्न ब्लॉकों के अंदर एक ही संग्रहीत ब्लॉक का प्रतिपादन), लेकिन मुझे लगा कि मैं इसे इंगित करूंगा।
अजय

3

मैं भी अपने टेम्पलेट फ़ाइलों में एक दोहराया {% ब्लॉक%} के लिए एक ही जरूरत भर में आए हैं। मुद्दा यह है कि मैं एक Django सशर्त के किसी भी मामले में एक Django {% ब्लॉक%} का उपयोग करना चाहता हूं, और मैं चाहता हूं कि बाद की फ़ाइलों द्वारा {% block%} को वर्तमान फ़ाइल का विस्तार करने वाली फ़ाइलों से अधिक-योग्य बनाया जा सके। (इसलिए इस मामले में, मैं जो चाहता हूं वह निश्चित रूप से एक चर की तुलना में अधिक ब्लॉक है क्योंकि मैं तकनीकी रूप से इसे फिर से उपयोग नहीं कर रहा हूं, यह सिर्फ एक सशर्त के दोनों छोर पर दिखाई देता है।

समस्या:

निम्नलिखित Django टेम्प्लेट कोड के परिणामस्वरूप एक टेम्पलेट सिंटैक्स त्रुटि होगी, लेकिन मुझे लगता है कि यह एक मान्य "चाहता है" है कि एक परिभाषित {% ब्लॉक%} को फिर से एक सशर्त में उपयोग किया जाता है (IE, क्यों बीएचओएच के लिए सिंटैक्स को सत्यापित करने वाला Django पार्सर समाप्त होता है एक शर्त के अनुसार, क्या यह केवल TRUTHY शर्त को मान्य नहीं करना चाहिए? '

# This example shows a {{ DEBUG }} conditional that loads 
#   Uncompressed JavaScript files if TRUE 
#   and loads Asynchronous minified JavaScript files if FALSE.  

# BASE.html
{% if DEBUG %}
    <script src="{{MEDIA_URL}}js/flatfile.1.js"></script>
    <script src="{{MEDIA_URL}}js/flatfile.2.js"></script>
    <script src="{{MEDIA_URL}}js/flatfile.3.js"></script>
    <script type="text/javascript">
        {% block page_js %}
            var page = new $site.Page();
        {% endblock page_js %}
    </script>
{% else %}
    <script type="text/javascript">
        // load in the PRODUCTION VERSION of the site
        // minified and asynchronosly loaded
        yepnope([
            {
                load : '{MEDIA_URL}}js/flatfiles.min.js',
                wait : true,
                complete : function() {
                    {% block page_js %} // NOTE THE PAGE_JS BLOCK
                        var page = new $site.Page();
                    {% endblock page_js %}
                }
            }
        )];
    </script>
{% endif %}

# ABOUT.html
{% extends 'pages/base.html' %}
{% block page_js %}
var page = new $site.Page.About();
{% endblock page_js %}

समाधान:

सशर्त रूप से {% ब्लॉक%} को एक से अधिक बार सम्मिलित करने के लिए आप {% शामिल%} का उपयोग कर सकते हैं। यह मेरे लिए काम किया क्योंकि Django सिंटैक्स चेकर में केवल TRUTHY {% में%} शामिल हैं। नीचे देखें रिजल्ट:

# partials/page.js
{% block page_js %}
    var page = new $site.Page();    
{% endblock %}

# base.html
{% if DEBUG %}
    <script src="{{MEDIA_URL}}js/flatfile.1.js"></script>
    <script src="{{MEDIA_URL}}js/flatfile.2.js"></script>
    <script src="{{MEDIA_URL}}js/flatfile.3.js"></script>
    <script type="text/javascript">
        {% include 'partials/page_js.html' %}
    </script>
{% else %}
    <script type="text/javascript">
        yepnope([
            {
                load : '{MEDIA_URL}}js/flatfiles.min.js',
                wait : true,
                complete : function() {
                    {% include 'partials/page_js.html' %}
                }
            }
        )];
    </script>
{% endif %}


1

इसके लिए दो आसान उपाय हैं।

सबसे आसान है कि आप अपने शीर्षक को एक संदर्भ चर में डाल दें। आप संदर्भ चर को अपने विचार में सेट करेंगे।

यदि आप जेनेरिक विचारों जैसे कुछ का उपयोग कर रहे हैं और चित्रों, बिल्लियों इत्यादि के लिए एक व्यूहोम नहीं है, तो आप कस्टम टेम्पलेट टैग के रास्ते पर जा सकते हैं जो संदर्भ में एक चर सेट करता है

इस मार्ग पर जाने से आप कुछ कर पाएंगे:

{% extends "base.html" %}
{% load set_page_title %}
{% page_title "My Pictures" %}
...

फिर अपने आधार में। html:

...
{% block title %}{{ page_title }}{% endblock %}
...
<h1>{{ page_title }}</h1>

हालाँकिAny variable set in the context will only be available in the same block of the template in which it was assigned. This behavior is intentional; it provides a scope for variables so that they don’t conflict with context in other blocks.
जोनाथन

0

चयनित उत्तर दोनों को समान मूल्य देने के लिए बाल टेम्प्लेट में एक टैग के अंदर एक टैग को लपेटने के लिए एक आसान हल करने के लिए दृष्टिकोण देता है। मैं इसका उपयोग सामाजिक छवियों के लिए करता हूं।

बाल टेम्पलेट:

{% extends 'base.html' %}
...
{% block meta_image %}
{% block meta_image_secure %}
{% if object.cover_pic %}
{{ object.cover_pic.url }}
{% else %}
https://live-static.welovemicro.com/static/img/device-dark.png
{% endif %}
{% endblock %}
{% endblock %}
...

फिर जनक में base.html:

...
<meta property="og:image" itemprop="image" content="{% block meta_image %}https://live-static.welovemicro.com/static/img/device-dark.png{% endblock %}">
<meta property="og:image:secure_url" itemprop="image" content="{% block meta_image_secure %}https://live-static.welovemicro.com/static/img/device-dark.png{% endblock %}">
...

-3

में टहनी आप इस तरह बना सकते हैं:

# base.html
<html>
    <head>
        <title>{{ block('title') }}</title>
    </head>
    <body>
        <h1>{{ block('title') }}</h1>
    </body>
</html>

# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}

# pictures.html
{% extends 'base.html' %}
{% block title %}My Pictures{% endblock %}

# cats.html
{% extends 'base.html' %}
{% block title %}My Cats{% endblock %}

3
यह Django के बारे में एक सवाल है।
फ्रांस्वा कॉन्स्टेंट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.