2012-05-17 29 views
7

Tôi đang cố gắng để làm một cái gì đó như thế này:Làm cách nào để gián tiếp gọi macro trong mẫu Jinja2?

{% macro obj_type_1 %} 
stuff 
{% endmacro %} 
{% macro obj_type_2 %} 
stuff 
{% endmacro %} 

{{ (obj|get_type)(obj) }} 

Trong ví dụ này, get_type là một bộ lọc mà sẽ trở obj_type_1 hoặc obj_type_2 - tức là, tên của các vĩ mô để kêu gọi obj. Tôi không muốn đánh dấu obj với đầu ra cấu hình vì ngay bây giờ obj được sử dụng trong một số mẫu làm dữ liệu cấu trúc, được hiển thị với đánh dấu khác nhau tùy thuộc vào ngữ cảnh.

Tôi biết cú pháp ở đây hơi bị tra tấn, nhưng tôi nghĩ đó là vì những gì tôi muốn làm là không thể ngay lập tức trong các mẫu Jinja. Tôi đang cố gắng để thay thế một schwack damn lớn nếu/elif/khác crap trong một số mã thế hệ cấu hình với các mẫu, nhưng bit này có vẻ là một điểm gắn bó.

+0

Vì vậy, bạn đang về cơ bản tìm kiếm một cách để 'eval()' trong Jinja2? – Blender

+0

Gần; Tôi muốn gọi macro theo tên. –

Trả lời

0

Cá nhân, vì get_type được sử dụng làm người điều phối, sẽ rõ ràng hơn khi triển khai nó dưới dạng macro jinja gọi macro chuyên biệt dựa trên loại obj. Điều này loại bỏ sự cần thiết cho nó để trả về một macro có thể gọi và, đồng thời, hợp nhất các macro chuyên biệt và logic quy định cách thức/khi chúng được sử dụng.

8

Bạn có thể tạo bộ lọc Jinja2 lấy Macro từ ngữ cảnh hiện tại và sau đó đánh giá Macro. Bộ lọc này là:

@contextfilter 
def call_macro_by_name(context, macro_name, *args, **kwargs): 
    return context.vars[macro_name](*args, **kwargs) 

Nếu ứng dụng của bạn yêu cầu, bạn có thể thực hiện chuỗi thao tác trên macro_name trước khi nhìn lên các Macro trong context.vars.

Đây là một ví dụ đầy đủ:

#!/usr/bin/env python 
from jinja2 import Environment, contextfilter 

@contextfilter 
def call_macro_by_name(context, macro_name, *args, **kwargs): 
    return context.vars[macro_name](*args, **kwargs) 

template_string = """\ 
{%- macro MyMacro(item) %}MyMacro({{ item }}){% endmacro -%} 
{{ MyMacro('direct') }} 
{{ 'MyMacro' | macro('indirect') }} 
""" 

env = Environment() 
env.filters['macro'] = call_macro_by_name 
template = env.from_string(template_string) 
print(template.render()) 

mà in

MyMacro(direct) 
MyMacro(indirect) 
2

Macros chỉ có thể gọi bằng cách sử dụng nhập khẩu dict:

macros.html

{% macro render_foo(value) %} 
HELLO {{ value }}! 
{% endmacro %} 

my_view.html

{% import "macros.html" as my_macros %} 

{% set macro_name = 'render_' + dynamic_content %} 
{{ my_macros[macro_name]('world') }} 

render như:

HELLO world! 
Các vấn đề liên quan