2013-08-19 8 views
5

मैं अपने स्टैंडअलोन एप्लिकेशन के लिए Django टेम्पलेट सिस्टम द्वारा प्रीप्रोसेस्ड मानव-पठनीय एचटीएमएल और सीएसएस कोड (ठीक से इंडेंट) उत्पन्न करना चाहता हूं।Django टेम्पलेट्स में उचित इंडेंटेशन (बंदर-पैचिंग के बिना)?

मैंने django.template.base मॉड्यूल में मिले नोडलिस्ट क्लास से रेंडर विधि संशोधित की है। मेरा कोड ठीक से काम करता प्रतीत होता है, लेकिन मैं पुराने रेंडर विधि को बदलने के लिए बंदर-पैचिंग का उपयोग कर रहा हूं।

क्या कोई और शानदार तरीका है जो इस मामले में बंदर-पैचिंग का उपयोग नहीं करता है? या शायद बंदर-पैचिंग यहां सबसे अच्छा तरीका है?

मेरे कोड इस तरह दिखता है:

''' 
This module monkey-patches Django template system to preserve 
indentation when rendering templates. 
''' 

import re 

from django.utils.encoding import force_text 
from django.utils.safestring import mark_safe 
from django.template.loader import render_to_string 
from django.template import Node, NodeList, TextNode 
from django.template.loader_tags import (BlockNode, ConstantIncludeNode, 
             IncludeNode) 


NEWLINES = re.compile(r'(\r\n|\r|\n)') 
INDENT = re.compile(r'(?:\r\n|\r|\n)([\ \t]+)') 


def get_indent(text, i=0): 
    ''' 
    Depending on value of `i`, returns first or last indent 
    (or any other if `i` is something other than 0 or -1) 
    found in `text`. Indent is any sequence of tabs or spaces 
    preceded by a newline. 
    ''' 
    try: 
     return INDENT.findall(text)[i] 
    except IndexError: 
     pass 


def reindent(self, context): 
    bits = '' 
    for node in self: 
     if isinstance(node, Node): 
      bit = self.render_node(node, context) 
     else: 
      bit = node 
     text = force_text(bit) 

     # Remove one indentation level 
     if isinstance(node, BlockNode): 
      if INDENT.match(text): 
       indent = get_indent(text) 
       text = re.sub(r'(\r\n|\r|\n)' + indent, r'\1', text) 

     # Add one indentation level 
     if isinstance(node, (BlockNode, ConstantIncludeNode, IncludeNode)): 
      text = text.strip() 
      if '\r' in text or '\n' in text: 
       indent = get_indent(bits, -1) 
       if indent: 
        text = NEWLINES.sub(r'\1' + indent, text) 

     bits += text 

    return mark_safe(bits) 


# Monkey-patching Django class 
NodeList.render = reindent 
+0

मैं डीजेंगो के लिए बिल्कुल नया हूं, क्या आप एक उदाहरण प्रदान कर सकते हैं कि मैं इसे अपने प्रोजेक्ट में कैसे कार्यान्वित कर सकता हूं? –

उत्तर

1

आप वर्ग विरासत का उपयोग एक अलग NodeList बनाने के लिए कर सकता है लेकिन यह शायद एक अलग अंत पर कुछ पैचिंग की आवश्यकता होगी। आपका समाधान सादा और सरल लगता है।

class MyNodeList(NodeList): 
    def render(self, context): 
     # call super if you require so 
     # your reindent functionality 
3

टेम्पलेट परत में संशोधन करना, ठीक है, लेकिन इष्टतम नहीं होगी, क्योंकि यह केवल संभालती कैसे एक नोड प्रदान की गई है, न कि एक पूरे दस्तावेज। एचटीएमएल और सीएसएस पृष्ठों के लिए प्रस्तुत प्रतिक्रिया को सुंदर प्रिंट करने के लिए मैं आपकी परियोजना के लिए writing custom middleware की अनुशंसा करता हूं।

आपका मिडलवेयर process_template_response जो देखने के लिए इस्तेमाल किया जाना चाहिए, लागू करने और SimpleTemplateResponse वस्तु को अद्यतन करने की आवश्यकता होगी:

  • is_rendered विशेषता की जांच करके पता प्रतिक्रिया प्रदान की गई है
  • या तो द्वारा दस्तावेज़ प्रकार सत्यापित करें :
    • template_name विशेषता के अंत में वांछित फ़ाइल प्रकार (.html, .css) के लिए खोज रहे
    • ,210
    • (Django 1.5) या संभवतः पुराने
  • फिर से प्रारूप को स्थापित करता है और भव्य देखने के लिए अपने गाया दस्तावेज़ अद्यतन (Beautiful Soup एचटीएमएल के लिए अच्छा है, लेकिन आप अपने preffered से लेनी होगी के लिए mimetypecontent_type विशेषता को देखते हुए सुंदर प्रिंटर या अपना खुद का रोल)।

मुझे लगता है कि मिडलवेयर एक बहुत ही सुरुचिपूर्ण समाधान है क्योंकि यह अंततः आपकी फ़ाइलों में कोई व्याख्यात्मक परिवर्तन नहीं करता है। यह पूरी तरह तर्क से अलग है जो आपकी टेम्पलेट सामग्री निर्धारित करता है (जहां इसका कोई व्यवसाय नहीं है)। अंत में, आप अपने सभी एचटीएमएल और सीएसएस को शानदार दिखाना चाहते हैं, तो अपने टेम्पलेट्स को पहली जगह क्यों बांधें?

संबंधित मुद्दे