2013-08-19 14 views
5

Bağımsız uygulamam için Django şablon sistemi tarafından önceden işlenen insan tarafından okunabilir HTML ve CSS kodu (uygun şekilde girintili) oluşturmak istiyorum.Django şablonlarında uygun bir girinti (maymun yama olmadan)?

Django.template.base modülünde bulunan NodeList sınıfından render yöntemini değiştirdim. Kodum düzgün çalışıyor gibi görünüyor, ancak eski render yöntemini değiştirmek için maymun düzeltme kullanıyorum.

Bu durumda maymun yamasını kullanmayan daha zarif bir yol var mı? Ya da belki de maymun-yama, burada en iyi yoldur?

Benim kod şöyle görünür:

''' 
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

Django’ya oldukça yeni geldim, bunu projemde nasıl uygulayabileceğimin bir örneğini verebilir misiniz? –

cevap

1

Farklı NodeList oluşturmak için sınıf mirası kullanabilirsiniz ama muhtemelen farklı bir ucunda bazı yama gerektirecektir. Çözümünüz sade ve basit görünüyor.

3

Şablon katmanını değiştirmek iyi olur, ancak en uygun değildir, çünkü bir belgenin tamamını değil, yalnızca bir düğümün nasıl işlendiğini işler. Projenizde html ve css sayfaları için oluşturulan yanıtı güzel yazdırmak için writing custom middleware'u öneririm.

Kişisel katman SimpleTemplateResponse nesneyi görüntülemek için kullanılması gereken process_template_response uygulamak ve güncellemeniz gerekir: tepkisi

  • biri tarafından doküman türünü doğrulama hale getirilmesi durumunda

    • görmek is_rendered niteliğini kontrol :
      • template_name öznitelik sonunda istenen dosya tipi (.html, .css) arıyorsunuz
      • (Django 1.5) veya
    • Yeniden biçim yükler ve Beautiful Soup HTML için mükemmeldir (muhteşem bakmak için render belgeyi güncellemek, ancak tercih ettiği gerkeceği üstü için muhtemelen mimetypecontent_type özniteliği baktığımızda
    • güzel yazıcı veya kendi rulo.

    Bence Middleware çok daha zarif bir çözümdür, çünkü sonuçta dosyalarınızda herhangi bir sözcüksel değişiklik yapmaz. Şablon içeriğinizi belirleyen (iş bulunmayan) mantıktan tamamen ayrılmıştır. Son olarak, html'nizin ve css'inizin harika görünmesini istersiniz, o zaman neden bunları şablonlarınıza ilk olarak bağlarsınız?

  • İlgili konular