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
नए संस्करणों में (मैं जिंजा 2 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))
सेमीजॉन मोसेिंगर

1
यहां तक ​​कि 8 साल बाद, यदि आप फ्लास्क का उपयोग कर रहे हैं, तो यह हाल के किसी भी उत्तर की तुलना में क्लीनर समाधान की तरह लगता है। और @ffghfgh से पुराने प्रश्न का उत्तर देने के लिए, हाँ - आप कई फ़ंक्शन पास कर सकते हैं।
केविनमीक जूल 26'19

133

नोट: यह फ्लास्क विशिष्ट है!

मुझे पता है कि यह पोस्ट काफी पुरानी है, लेकिन संदर्भ प्रोसेसर के उपयोग से फ्लास्क के नए संस्करणों में ऐसा करने के बेहतर तरीके हैं।

चर आसानी से बनाए जा सकते हैं:

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

ऊपर इस तरह के फ्लास्क के साथ एक 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__)वहां घोषित हैं।
लियाम स्टेनली

6
जिंजा 2 के बारे में पूछे गए प्रश्न के अनुसार नीचे मतदान किया गया और उत्तर फ्लास्क विशिष्ट है।
एजेपी

13
@AJP अभी भी सैद्धांतिक रूप से सवाल का जवाब देता है। यह समस्या को हल करने का एक तरीका है, बशर्ते आप फ्लास्क का उपयोग कर रहे हों। सभी जावास्क्रिप्ट सवालों की तरह एक बिट अक्सर jQuery के साथ या बिना विकल्प देने के जवाब देते हैं या अजगर के बारे में सवाल अक्सर पायथन 2 और 3 के लिए दोनों का जवाब देते हैं। यह सवाल फ्लास्क को छोड़कर नहीं था। (Py2 के बारे में एक प्रश्न के विपरीत एक Py3 उत्तर को बाहर कर देगा)। इस जवाब से मुझे मदद मिली।
जेरोमेज

2
बहुत मददगार, और बस मैं जो चाह रहा था। जिंजा 2 एक वेब फ्रेमवर्क का हिस्सा है, और जैसा कि बैक-एंड से पूरी तरह से स्वतंत्र नहीं है। मैं पाइथन और इस पोस्ट के साथ Django और फ्लास्क दोनों में काम करता हूं, साथ ही यहां अन्य लोग मेरे लिए प्रासंगिक हैं। एक प्रश्न को निर्दिष्ट करने की कोशिश करना मेरी राय में उतना ही हानिकारक है जितना कि अनावश्यक रूप से अस्पष्ट।

76

मुझे लगता है कि जिन्जा जानबूझकर एक टेम्पलेट के भीतर 'मनमाना' अजगर चलाना मुश्किल बनाता है। यह इस राय को लागू करने की कोशिश करता है कि टेम्प्लेट में कम तर्क एक अच्छी बात है।

आप 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। हां, आप नाम स्थान (मॉड्यूल), फ़ंक्शंस, क्लास इंस्टेंसेस आदि को 'इंजेक्ट' कर सकते हैं, यह उपयोगी है, लेकिन अन्य टेम्पलेट इंजनों की तरह लचीला नहीं है। फिर भी, जिंजा के पास अन्य अच्छे बिंदु हैं। मैं आभारी हूँ अगर आप जवाब स्वीकार करते हैं अगर यह :) :)
रॉब कौवी

मेरे ऐप इंजन प्रोजेक्ट (webapp2 और jinja2) को करते हुए मेरे लिए चाल चली। धन्यवाद
सोजन वी जोस

@RobCowie ने env.globals में चतुर_फंक्शन जोड़ने के बाद, टेम्पलेट से फ़ंक्शन को कैसे कॉल किया जा सकता है।
जॉर्ज विदिशा

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

आप मैट्रॉस्किन के उत्तर के अनुसार फ़ील्ड में फ़ंक्शन भी दे सकते हैं

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

उत्पादन होगा:

Hey, my name is Jay Kay

जिनजा 2 संस्करण 2.7.3 के साथ काम करता है

और यदि आप चाहते हैं कि एक डेकोरेटर ब्रूनो ब्रोंस्की के उत्तर कीtemplate.globals जांच करने के कार्यों को परिभाषित करने में आसानी करे


8
शायद इसलिए कि आपने बाकी सभी के जवाबों को
खारिज कर दिया

13
@ बोरोकोवसेव यह एक अच्छा कारण नहीं है। मैंने केवल 2 जवाब दिए; जवाब जो कि Jinja2 के बजाय फ्लास्क के बारे में थे। यदि वे विषय पर और जिंजा 2 के बारे में अपने उत्तर संपादित करना चाहते हैं तो मैं उन्हें वोट दूंगा।
एजेपी

टीएक्स @BorkoKovacev :)
AJP

1
मैंने इस उत्तर का एक फ़ंक्शन डेकोरेटर संस्करण बनाया। यह वर्तमान में 0 वोटों के साथ सबसे नीचे है: - ( stackoverflow.com/a/47291097/117471
ब्रूनो ब्रोंस्की

2
@BrunoBronosky अच्छा है। मतदान किया है :) ... इसे एक और दशक दे दो और यह मेरी तुलना में अधिक हो सकता है: पी ... कभी भी फ्लास्क को नहीं पकड़ेगा; पी
एजेपी

25

मुझे @ AJP का जवाब पसंद है । जब तक मैं बहुत सारे कार्यों के साथ समाप्त नहीं हो गया, मैंने इसका उपयोग किया। फिर मैंने पायथन फंक्शन डेकोरेटर पर स्विच किया ।

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

@ ममता_सिटी, हां। पायथन फ़ंक्शन डेकोरेटर लिंक पढ़ें। उत्तम सामग्री!
ब्रूनो ब्रोंस्की

1
@BrunoBronosky अजगर सज्जाकारों के लिए एक समझदार और स्वच्छ उपयोग का उत्कृष्ट प्रदर्शन। महान पद!
dreftymac

1
क्या एक महान कार्यान्वयन!
फिलिप ओगर

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})

यह उत्तर अब तक का सर्वश्रेष्ठ इम्हो है। आप बस फ़ंक्शन को उसी तरह से टेम्पलेट में पास करते हैं जिस तरह से आप एक मान पास करते हैं, सभी कार्यों के बाद अजगर में प्रथम श्रेणी के नागरिक हैं :)
मार्क कोर्टिंक

8

टेम्पलेट को अपने मुख्य कोड से जोड़ने के लिए एक लैम्ब्डा का उपयोग करें

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

फिर आप टेम्पलेट में फ़ंक्शन को मूल रूप से कॉल कर सकते हैं

{{clever_function(value)}}

1
लंबोदर कार्यों का चतुर उपयोग।

23
@odiumediae: नहीं, यह नहीं है। यह पूरी तरह से अनावश्यक है। बस फ़ंक्शन को स्वयं पास करें: चालाक_फंक्शन = चतुर_फंक्शन
1

@vezult मैं देख रहा हूँ। मुझे वह कैसे याद आ सकता है? इसे साफ करने के लिए धन्यवाद!

6

जिनजा 2 से एक पायथन फ़ंक्शन को कॉल करने के लिए, आप कस्टम फ़िल्टर का उपयोग कर सकते हैं जो ग्लोबल्स के समान काम करते हैं: 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' 

फिर अपने दृश्य फ़ंक्शन में अपनी कक्षा का एक उदाहरण बनाएं और परिणामी वस्तु को अपने टेम्पलेट के लिए रेंडर_template फ़ंक्शन के पैरामीटर के रूप में पास करें

my_obj = Test_jinja_object()

अब अपने टेम्प्लेट में, आप जीजा में क्लास के तरीकों को कॉल कर सकते हैं

{{ my_obj.clever_function () }}

समतुल्य और थोड़ा सरल तरीका: किसी मॉड्यूल में टेम्प्लेट के लिए सभी फ़ंक्शन डालें, उस मॉड्यूल को आयात करें और इसे टेम्प्लेट ग्लोबल के रूप में जोड़ें। एक मॉड्यूल एक ऐसी वस्तु है जिसमें फ़ंक्शन्स हैं :) (लेकिन विधियाँ नहीं हैं - आत्म-परम की कोई आवश्यकता नहीं है और किसी भी वर्ग का पुनर्निमाण नहीं है!)
Araujo

@ NeedricAraujo क्या होगा अगर मुझे केवल एक या दो टेम्पलेट में कार्यों के सेट की आवश्यकता है और उन सभी को नहीं। इसके अलावा, क्या होगा अगर मुझे अलग-अलग जिंजस टेम्प्लेट में अजगर कार्यों के विभिन्न सेटों की आवश्यकता है? क्या आप अभी भी उन सभी को टेम्पलेट ग्लोबल्स के रूप में आयात करने के लिए प्रभावी मानते हैं, बल्कि उन्हें एक कक्षा में विधियों के रूप में डालते हैं और केवल उन तरीकों से कक्षाओं को पास करते हैं जिनकी आपको ज़रूरत है।
कुदहिनबु ओलुवापोनले

केवल विशिष्ट टेम्पलेट्स में उपयोग करने के लिए, मैं फ़ंक्शन (या एक मॉड्यूल युक्त फ़ंक्शन) को केवल उस टेम्पलेट संदर्भ से जोड़ूंगा जो उन टेम्पलेट्स का उपयोग करने वाले विचारों से पीछे हट गया है।
18ric अरुजो

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.exception.UndefinedError: 'y' अपरिभाषित है
lww

हाँ, में test.html foo उपयोग करने के लिए माना जाता है cuz
luckyguy73
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.