2009-09-29 17 views
15

Tôi đã tạo thẻ bao gồm, tuy nhiên tôi muốn có thể tạo mẫu tùy chọn có thể định cấu hình. Có vẻ như không hỗ trợ cho việc này, vì vậy tôi muốn xem cách mọi người làm điều này - có thể một phương pháp tìm kiếm thư mục mẫu trước tiên cho một tên mẫu cụ thể và sau đó quay trở lại mẫu mặc định.Thẻ kết hợp Django với mẫu có thể định cấu hình

@register.inclusion_tag('foo.html', takes_context=True) 
+0

Bạn đang cố gắng đạt được điều đó '{% bao gồm my_template%}' có thể không? –

+0

Tôi cần thêm một số biến vào ngữ cảnh bằng thẻ tùy chỉnh. Có vẻ như tôi sẽ phải viết thẻ theo cách dài. Cảm ơn. – meppum

Trả lời

4

Trình trang trí inclusion_tag chỉ là một phím tắt - nó có nghĩa là cách đơn giản để hiển thị mẫu cụ thể với ngữ cảnh cụ thể. Ngay sau khi bạn muốn di chuyển ra ngoài đó, nó không còn có thể giúp bạn. Nhưng điều đó có nghĩa là bạn sẽ phải viết thẻ theo cách dài, như được giải thích trong tài liệu và chuyển mẫu bạn muốn làm tham số.

3

Tôi đã phải làm một cái gì đó như thế này cho một dự án và kể từ khi chúng tôi cần nhiều hơn một loại thẻ bao gồm tôi đã thực hiện một trang trí dựa trên trang trí django inclusion_tag. Đây là mã:

# -*- coding: utf-8 -*- 
from django import template 
from inspect import getargspec 
from django.template.context import Context 
from django.template import Node, generic_tag_compiler, Variable 
from django.utils.functional import curry 


def inclusion_tag(register, context_class=Context, takes_context=False): 
    def dec(func): 
     params, xx, xxx, defaults = getargspec(func) 
     if takes_context: 
      if params[0] == 'context': 
       params = params[1:] 
      else: 
       raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'") 

     class InclusionNode(Node): 
      def __init__(self, vars_to_resolve): 
       self.vars_to_resolve = map(Variable, vars_to_resolve) 

      def render(self, context): 
       resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] 
       if takes_context: 
        args = [context] + resolved_vars 
       else: 
        args = resolved_vars 

       file_name, extra_context = func(*args) 

       from django.template.loader import get_template, select_template 
       if not isinstance(file_name, basestring) and is_iterable(file_name): 
        t = select_template(file_name) 
       else: 
        t = get_template(file_name) 
       self.nodelist = t.nodelist 
       new_context = context_class(extra_context, autoescape=context.autoescape) 
       # Copy across the CSRF token, if present, because inclusion 
       # tags are often used for forms, and we need instructions 
       # for using CSRF protection to be as simple as possible. 
       csrf_token = context.get('csrf_token', None) 
       if csrf_token is not None: 
        new_context['csrf_token'] = csrf_token 
       return self.nodelist.render(new_context) 

     compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode) 
     compile_func.__doc__ = func.__doc__ 
     register.tag(getattr(func, "_decorated_function", func).__name__, compile_func) 
     return func 
    return dec 

Bạn phải trả lại một bộ dữ liệu với mẫu (hoặc danh sách mẫu) và ngữ cảnh ngữ cảnh. Lưu ý rằng bạn phải vượt qua thanh ghi (Thư viện chẳng hạn) trong các cuộc gọi trang trí:

from somewhere import inclusion_tag 
@inclusion_tag(register) 
def display_formset(formset): 
    template_name = FORMSET_TEMPLATES.get(formset.model, 
     'includes/inline_formset.html') 
    return (template_name, {'formset': formset}) 

Hope this helps

+0

Bất kỳ ý tưởng làm thế nào để cập nhật này cho django 1.4? Bây giờ generic_tag_compiler cần các đối số mã thông báo và phân tích cú pháp – Gattster

28

tôi sử dụng simple_tag khi tôi cần phải làm điều đó:

from django.template import Library, loader, Context 

@register.simple_tag(takes_context=True) 
def my_tag(context, template_name): 

    var1 = ... 

    t = loader.get_template(template_name) 
    return t.render(Context({ 
     'var1': var1, 
     ... 
    })) 
7

bài này cứu lấy mạng sống của tôi: http://djangosnippets.org/snippets/1329/

Điều quan trọng là thêm vào "mẫu giả":

{% extends template %} 
+0

Đây là một mẹo tuyệt vời! Thậm chí tốt hơn, '@ register.inclusion_tag' có thể lấy một cá thể' Template' (ngoài đường dẫn), vì vậy bạn có thể làm một cái gì đó như 'dummy = Template (" "" {% extends template%} "" ")', sau đó '@ register.inclusion_tag (giả, takes_context = True)'. '' ' – Emil

0

Giải pháp có thể là số inclusion_tag thông thường chuyển tên mẫu động tới context.

Như thế này:

# templatetags/tags.py 

@register.inclusion_tag('include_tag.html', takes_context=True) 
def tag_manager(context): 
    context.update({ 
     'dynamic_template': resolve_template(context), 
    }) 
    return context 

Và mẫu:

<!-- include_tag.html --> 

{% include dynamic_template %} 

Các thủ thuật ở đây là, khi tôi gọi {% tag_manager %}, nó bao gồm mà lần lượt bao gồm các mẫu được trả về bởi resolve_template() (không bao gồm cho ngắn gọn).

Hy vọng điều này sẽ giúp ...

Các vấn đề liên quan