jinja2에서 파이썬 함수 호출


144

jinja2를 사용하고 있으며 매크로를 호출하는 것과 유사한 구문을 사용하여 파이썬 함수를 도우미로 호출하고 싶습니다. jinja2는 함수 호출을 막기위한 의도로 보이며 함수를 템플릿에 매크로로 복사하여 반복 할 것을 주장합니다.

이 작업을 수행하는 간단한 방법이 있습니까? 그리고 전체 파이썬 함수를 가져 와서 많은 확장 기능을 작성하는 등 리가 마롤을 거치지 않고 jinja2에서 액세스 할 수있는 방법이 있습니까?

답변:


223

플라스크를 사용하는 사람들은 이것을 다음에 넣으십시오 __init__.py.

def clever_function():
    return u'HELLO'

app.jinja_env.globals.update(clever_function=clever_function)

템플릿에서 {{ clever_function() }}


이처럼 여러 기능을 전달할 수 있습니까?
ffghfgh

6
최신 버전 (Jinja2 2.9.6을 사용하고 있음)에서는 훨씬 쉽게 작동하는 것 같습니다. 변수를 사용할 때와 같이 함수를 사용하십시오 (보다 복잡한 상황에서도 작동).from jinja2 import Template ##newline## def clever_function(): ##newline## return "Hello" ##newline## template = Template("{{ clever_function() }}") ##newline## print(template.render(clever_function=clever_function))
Semjon Mössinger

1
8 년이 지난 후에도 Flask를 사용하는 경우 가장 최근의 답변보다 깨끗한 솔루션처럼 보입니다. 그리고 @ffghfgh의 이전 질문에 대답하기 위해 여러 기능을 전달할 수 있습니다.
kevinmicke

133

참고 : 이것은 플라스크 전용입니다!

이 게시물이 상당히 오래되었다는 것을 알고 있지만 컨텍스트 프로세서를 사용하여 최신 버전의 Flask 에서이 작업을 수행하는 더 좋은 방법이 있습니다.

변수를 쉽게 만들 수 있습니다 :

@app.context_processor
def example():
    return dict(myexample='This is an example')

위와 같이 Flask를 사용하는 Jinja2 템플릿에서 사용할 수 있습니다.

{{ myexample }}

(어떤 출력 This is an example)

본격적인 기능뿐만 아니라 :

@app.context_processor
def utility_processor():
    def format_price(amount, currency=u'€'):
        return u'{0:.2f}{1}'.format(amount, currency)
    return dict(format_price=format_price)

위와 같이 사용하면 위와 같습니다.

{{ format_price(0.33) }}

(통화 기호와 함께 입력 가격을 출력하는 경우)

또는 플라스크에 구운 진자 필터를 사용할 수 있습니다 . 예 : 데코레이터 사용 :

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

또는 데코레이터없이 수동으로 기능을 등록하십시오.

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter

위의 두 가지 방법으로 적용된 필터는 다음과 같이 사용할 수 있습니다.

{% for x in mylist | reverse %}
{% endfor %}

4
이 함수들은 어디에 존재해야합니까?
knk

3
__init__.py당신이 flask.Flask(__name__)거기 선언했다고 가정합니다 .
Liam Stanley

6
Jinja2에 대한 질문과 투표가 Flask에 따라 내려졌습니다.
AJP

13
@AJP 여전히 이론적으로 질문에 대답합니다. 이것은 Flask를 사용하고 있기 때문에 문제를 해결하는 한 가지 방법입니다. 모든 JavaScript 질문과 마찬가지로 jQuery의 유무에 관계없이 대안을 제공하거나 Python에 대한 질문은 종종 Python2와 3 모두에 대해 답변합니다. Flask를 배제하지 않았습니다. (Py2에 대한 질문과 달리 Py3 답변은 제외됩니다). 이 답변이 도움이되었습니다.
jeromej

2
매우 유용하고 내가 찾던 것. Jinja2는 웹 프레임 워크의 일부이므로 백엔드와 완전히 독립적이지 않습니다. 나는 Django와 Flask에서 Python 과이 게시물을 사용하며 여기의 다른 사람들도 나와 관련이 있습니다. 질문을 과도하게 지정하려고 시도하는 것은 불필요하게 모호한 것처럼 내 의견으로는 해 롭습니다.

76

jinja가 의도적으로 템플릿 내에서 '임의'파이썬을 실행하는 것을 어렵게 만듭니다. 템플릿의 로직이 적을수록 좋다는 견해를 강요합니다.

Environment인스턴스 내에서 글로벌 네임 스페이스를 조작 하여 함수에 대한 참조를 추가 할 수 있습니다. 템플릿을로드 하기 전에 수행해야합니다 . 예를 들면 다음과 같습니다.

from jinja2 import Environment, FileSystemLoader

def clever_function(a, b):
    return u''.join([b, a])

env = Environment(loader=FileSystemLoader('/path/to/templates'))
env.globals['clever_function'] = clever_function

5
나는 또한 이것을 발견했다 – 당신은 다음과 같은 것을 사용하여 모듈을 추가 할 수있다 : import utils.helpers env.globals['helpers'] = utils.helpers
Lee

@남자 이름. 예, 네임 스페이스 (모듈), 함수, 클래스 인스턴스 등을 '주입'할 수 있습니다. 유용하지만 mako와 같은 다른 템플릿 엔진만큼 유연하지는 않습니다. 그래도 jinja에는 다른 좋은 점이 있습니다. 도움이된다면 답변을 수락하면 감사하겠습니다 :)
Rob Cowie

내 앱 엔진 프로젝트 (webapp2 및 jinja2)를 수행하는 동안 나를 위해 트릭을 수행했습니다. 감사합니다
Sojan V Jose

사전 env.globals에 clever_function을 추가 한 후 @RobCowie, 템플릿에서 함수를 호출하는 방법.
Jorge Vidinha

1
따라서, {{ clever_function('a', 'b') }}
롭 코위

41
from jinja2 import Template

def custom_function(a):
    return a.replace('o', 'ay')

template = Template('Hey, my name is {{ custom_function(first_name) }} {{ func2(last_name) }}')
template.globals['custom_function'] = custom_function

Matroskin의 답변 에 따라 필드에서 기능을 제공 할 수도 있습니다

fields = {'first_name': 'Jo', 'last_name': 'Ko', 'func2': custom_function}
print template.render(**fields)

출력합니다 :

Hey, my name is Jay Kay

Jinja2 버전 2.7.3에서 작동

브루노 브로 노 스키의 답변template.globals확인하면서 데코레이터가 함수를 쉽게 정의 할 수있게 하려면


8
아마 당신은 다른 사람의 답변을
공언

13
@BorkoKovacev 좋은 이유가 아닙니다. 나는 2 개의 답변 만 투표했다. Jinja2보다는 Flask에 대한 답변. 그들이 주제와 Jinja2에 관한 답변을 편집하고 싶다면 투표 해 드리겠습니다.
AJP

Tx @BorkoKovacev :)
AJP

1
이 답변의 함수 데코레이터 버전을 만들었습니다. 그것은 현재 0 표와 하단에 : - ( stackoverflow.com/a/47291097/117471
브루노 Bronosky

2
트윗 담아 가기 투표했습니다 :) ... 또 10 년을주고 내 것보다 높을 수도 있습니다 : P ... 절대로 플라스크를 잡을 수는 없습니다; P
AJP

25

@AJP의 답변이 마음에 듭니다 . 나는 많은 기능으로 끝날 때까지 그것을 그대로 사용했습니다. 그런 다음 Python 함수 데코레이터 로 전환했습니다 .

from jinja2 import Template

template = '''
Hi, my name is {{ custom_function1(first_name) }}
My name is {{ custom_function2(first_name) }}
My name is {{ custom_function3(first_name) }}
'''
jinga_html_template = Template(template)

def template_function(func):
    jinga_html_template.globals[func.__name__] = func
    return func

@template_function
def custom_function1(a):
    return a.replace('o', 'ay')

@template_function
def custom_function2(a):
    return a.replace('o', 'ill')

@template_function
def custom_function3(a):
    return 'Slim Shady'

fields = {'first_name': 'Jo'}
print(jinga_html_template.render(**fields))

좋은 기능에는 __name__!


1
이건 정말 멋지다. 파이썬에서 함수에 주석을 달면 함수 이름이 주석의 함수에 자동으로 전달됩니까?
mutant_city

@mutant_city, 예. 파이썬 함수 데코레이터 링크를 읽으십시오. 좋은 물건!
Bruno Bronosky

1
@BrunoBronosky 파이썬 데코레이터에게도 현명하고 깔끔한 사용에 대한 탁월한 데모. 좋은 포스트!
dreftymac

1
정말 훌륭한 구현입니다!
Philippe Oger

16

공식 문서 나 스택 오버플로에서 그런 간단한 방법을 보지 못했지만 이것을 발견했을 때 놀랐습니다.

# jinja2.__version__ == 2.8
from jinja2 import Template

def calcName(n, i):
    return ' '.join([n] * i)

template = Template("Hello {{ calcName('Gandalf', 2) }}")

template.render(calcName=calcName)
# or
template.render({'calcName': calcName})

이 대답은 지금까지 최고의 imho입니다. 모든 기능 : 파이썬에서 최고 수준의 시민 후에 당신은, 당신이 값을 전달 정확히 같은 방법으로 템플릿 기능을 통과
마크 Kortink

8

람다를 사용하여 템플릿을 기본 코드에 연결

return render_template("clever_template", clever_function=lambda x: clever_function x)

그런 다음 템플릿에서 함수를 완벽하게 호출 할 수 있습니다.

{{clever_function(value)}}

1
람다 함수의 영리한 사용법.

23
@odiumediae : 아뇨. 완전히 불필요합니다. 함수 핸들 자체를 전달하십시오. clever_function = clever_function
vezult

@vezult 알겠습니다. 어떻게 그리워? 정리해 주셔서 감사합니다!

6

Jinja2에서 파이썬 함수를 호출하려면 다음과 같이 전역과 유사하게 작동하는 사용자 정의 필터를 사용할 수 있습니다. http://jinja.pocoo.org/docs/dev/api/#writing-filters

매우 간단하고 유용합니다. myTemplate.txt 파일에서 다음과 같이 썼습니다.

{{ data|pythonFct }}

그리고 파이썬 스크립트에서 :

import jinja2

def pythonFct(data):
    return "This is my data: {0}".format(data)

input="my custom filter works!"

loader = jinja2.FileSystemLoader(path or './')
env = jinja2.Environment(loader=loader)
env.filters['pythonFct'] = pythonFct
result = env.get_template("myTemplate.txt").render(data=input)
print(result)

5

파이썬 함수 전체를 가져 와서 jinja2에서 액세스 할 수있는 방법이 있습니까?

그렇습니다. 위의 다른 답변 외에도이 기능이 효과적입니다.

클래스를 작성하고 관련 메소드로 채 웁니다 (예 :

class Test_jinja_object:

    def __init__(self):
        self.myvar = 'sample_var'

    def clever_function (self):
        return 'hello' 

그런 다음 뷰 함수에서 클래스의 인스턴스를 만들고 render_template 함수의 매개 변수로 결과 객체를 템플릿에 전달하십시오.

my_obj = Test_jinja_object()

이제 템플릿에서 jinja의 클래스 메소드를 호출 할 수 있습니다.

{{ my_obj.clever_function () }}

동등하고 약간 더 간단한 방법 : 템플릿의 모든 기능을 모듈에 넣고 해당 모듈을 가져 와서 템플릿 전역으로 추가합니다. 모듈은 기능 : 포함하는 객체입니다 (하지만 방법! - 자기 PARAM에 대한 필요와 reqiured없는 클래스)
의 Éric 아라 우호

@ ÉricAraujo 하나 또는 두 개의 템플릿으로 만 기능 집합이 필요하고 모든 기능이 아닌 경우 어떻게해야합니까? 또한 다른 jinjas 템플릿에 다른 python 함수 세트가 필요한 경우 어떻게해야합니까? 클래스의 메소드로 배치하지 않고 필요한 메소드 만 사용하여 클래스를 전달하는 대신 템플리트 글로벌로 모든 것을 가져 오는 것이 여전히 효과적이라고 생각하십니까?
Kudehinbu Oluwaponle

특정 템플릿에서만 사용하려면 해당 템플릿을 사용하는 뷰에 의해 다시 정의 된 템플릿 컨텍스트에만 함수 (또는 함수를 포함하는 모듈)를 추가합니다.
Éric Araujo

3

모든 내장 함수를 가져 오려면 다음을 사용할 수 있습니다.

app.jinja_env.globals.update(__builtins__)

추가 .__dict____builtins__문제가 해결되지 않을 경우.

John32323의 답변을 기반으로 합니다.


2

Django로 수행하는 경우 컨텍스트와 함께 함수를 전달할 수 있습니다.

context = {
    'title':'My title',
    'str': str,
}
...
return render(request, 'index.html', context)

이제 strjinja2 템플릿 의 기능 을 사용할 수 있습니다


1

훨씬 간단한 결정이 있습니다.

@app.route('/x')
def x():
    return render_template('test.html', foo=y)

def y(text):
    return text

그런 다음 test.html에서 :

{{ y('hi') }}

jinja2.exceptions.UndefinedError : 'y'는 정의되지 않았습니다
lww

예, cuz는 test.html에서 foo를 사용해야합니다
luckyguy73
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.