2009-09-29 10 views
15

Utworzono znacznik włączenia, jednak chciałbym móc uczynić szablon opcjonalnie konfigurowalnym. Wydaje się, że nie ma na to żadnego wsparcia, więc chciałbym zobaczyć, jak ludzie to robią - może metoda przeszuka najpierw katalog szablonów dla określonej nazwy szablonu, a następnie powróci do domyślnego szablonu.Znacznik dodawania Django z konfigurowalnym szablonem

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

Co próbujesz osiągnąć, że '{% include my_template%}' nie może? –

+0

Potrzebuję dodać niektóre zmienne do kontekstu za pomocą niestandardowego znacznika. Wygląda na to, że będę musiał napisać znacznik na dłuższą metę. Dzięki. – meppum

Odpowiedz

4

inclusion_tag dekorator jest tylko skrót - to oznaczało, jako prosty sposób renderowania konkretnego szablonu z konkretnym kontekście. Jak tylko chcesz wyjść poza to, nie może ci już pomóc. Ale to tylko oznacza, że ​​będziesz musiał napisać znacznik na dłuższą metę, jak wyjaśniono w dokumentacji, i przekazać szablon, który chcesz jako parametr.

3

Musiałem zrobić coś takiego dla projektu, a ponieważ potrzebowaliśmy więcej niż jednego tego rodzaju znacznika włączenia, stworzyłem dekoratora na podstawie dekoratora django inclusion_tag. To jest kod:

# -*- 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 

Musisz zwrócić krotkę z szablonem (lub listą szablonów) i kontekstowym dict. Należy pamiętać, że trzeba zdać rejestr (instancja Library) w wywołaniu dekorator:

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

Każdy pomysł, jak zaktualizować to dla django 1.4? Generic_tag_compiler wymaga teraz argumentów token i parser. – Gattster

28

używam simple_tag kiedy trzeba zrobić:

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

Ten post uratować moje życie: http://djangosnippets.org/snippets/1329/

kluczem jest dodać do szablonu „manekina”:

{% extends template %} 
+0

To jest świetna wskazówka! Co więcej, '@ register.inclusion_tag' może pobrać instancję' Template' (oprócz ścieżki), więc możesz zrobić coś w stylu 'dummy = Template (" "" {% extends template%} "" ")', następnie '@ register.inclusion_tag (dummy, takes_context = True)'. '' ' – Emil

0

Rozwiązaniem może być zwykły inclusion_tag, który przekazuje dynamiczną nazwę szablonu do context.

Jak to:

# 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 

A szablon:

<!-- include_tag.html --> 

{% include dynamic_template %} 

sztuczki tutaj jest, gdy zgłoszę {% tag_manager %}, zawiera który z kolei zawiera szablon zwrócony przez resolve_template() (nie dołączony dla zwięzłości).

Mam nadzieję, że to pomoże ...

Powiązane problemy