วิธีโหลดเทมเพลต jinja โดยตรงจากระบบไฟล์


88

เอกสาร Jinja API ที่ pocoo.orgฯ :

วิธีที่ง่ายที่สุดในการกำหนดค่า Jinja2 เพื่อโหลดเทมเพลตสำหรับแอปพลิเคชันของคุณมีลักษณะประมาณนี้:
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
สิ่งนี้จะสร้างสภาพแวดล้อมเทมเพลตด้วยการตั้งค่าเริ่มต้นและตัวโหลดที่ค้นหาเทมเพลตในโฟลเดอร์เทมเพลตภายในแพ็คเกจ python ของyourapplication

ปรากฎว่านี่ไม่ใช่เรื่องง่ายเพราะคุณต้องสร้าง / ติดตั้งแพคเกจ python ด้วยเทมเพลตของคุณซึ่งแนะนำความซับซ้อนที่ไม่จำเป็นมากมายโดยเฉพาะอย่างยิ่งหากคุณไม่มีเจตนาที่จะแจกจ่ายรหัสของคุณ คุณสามารถอ้างถึงคำถาม SO ในหัวข้อที่นี่และที่นี่แต่คำตอบนั้นคลุมเครือและไม่น่าพอใจ

สิ่งที่มือใหม่ไร้เดียงสาต้องการทำอย่างเห็นได้ชัดก็แค่โหลดเทมเพลตโดยตรงจากระบบไฟล์ไม่ใช่เป็นทรัพยากรในแพ็คเกจ วิธีนี้ทำได้อย่างไร?

คำตอบ:


130

มีวิธีการดังนี้: ใช้ a FileSystemLoaderแทนไฟล์PackageLoader. ผมพบว่าตัวอย่างบนเว็บที่นี่และที่นี่ สมมติว่าคุณมีไฟล์ python ใน dir เดียวกับเทมเพลตของคุณ:

./index.py
./template.html

index.py นี้จะค้นหาเทมเพลตและแสดงผล:

#!/usr/bin/python
import jinja2

templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader)
TEMPLATE_FILE = "template.html"
template = templateEnv.get_template(TEMPLATE_FILE)
outputText = template.render()  # this is where to put args to the template renderer

print(outputText)

ปรากฎว่าเอกสาร jinja2 API มีส่วนที่กล่าวถึงรถตักในตัวทั้งหมดดังนั้นจึงเป็นเรื่องน่าอายที่จะไม่สังเกตเห็นสิ่งนั้นในทันที แต่คำนำนั้นใช้คำในลักษณะที่PackageLoaderดูเหมือนจะเป็นวิธีเริ่มต้น "ง่ายที่สุด" สำหรับผู้ที่มาใหม่กับงูหลามสิ่งนี้สามารถนำไปสู่การไล่ล่าห่านป่า


96
คุณไม่สามารถโหลดเทมเพลตจากไฟล์ในบรรทัดเดียวได้เช่นjinja2.load_template('template.html')
Matt

4
ฉันมักจะมี Wrapper ที่ฉันเรียก Jinja2 ในแอปพลิเคชันของฉันโดยที่ฉันใส่คำฟุ่มเฟือยทั้งหมดนี้แล้วเรียกมันว่า:Jinja2.render(template_name, data)
Seraf

11
ความเสี่ยงด้านความปลอดภัยที่สำคัญ! jinja2.Environment(loader=templateLoader, autoescape=True)คุณเกือบจะแน่นอนต้องการที่จะเรียก หรือดูเอกสาร apiสำหรับข้อมูลเพิ่มเติม เพิ่งพบว่าฉันพบช่องโหว่ XSS ที่สำคัญจากการทำตามคำตอบนี้: /
andrewdotn

ลิงก์ทั้งสองด้านบนเสีย
ดู

77

วิธีที่ง่ายกว่าคือเรียกตัวjinj2.Templateสร้างโดยตรงและใช้openเพื่อโหลดไฟล์:

from jinja2 import Template
with open('template.html.jinja2') as file_:
    template = Template(file_.read())
template.render(name='John')

1
ขออภัยไม่อนุญาตให้ตั้งค่าตัวกรองแบบกำหนดเอง การโหลดเทมเพลตทำให้เกิดข้อผิดพลาดระหว่างการเริ่มต้นเนื่องจากยังไม่มีตัวกรองแบบกำหนดเอง และด้วยวิธีนี้คุณจะสามารถเข้าถึงสภาพแวดล้อมเท่านั้น (เพื่อรวมตัวกรอง) หลังจากเริ่มต้น
Ronan Paixão

18

นี่คือซับเดียว:

template = Template(open('template_file.j2').read())

จากนั้นคุณสามารถแสดงเทมเพลตในบรรทัดอื่นหรือสำหรับทั้งหมดในบรรทัดเดียว:

rendered = Template(open('template_file.j2').read()).render(var="TEXT")

1
น่าเสียดายที่สิ่งนี้จะพังหากมีการสืบทอดเทมเพลตเนื่องจาก Jinja จะไม่สามารถค้นหาเทมเพลตที่อ้างอิงได้
Bemmu

4
แต่โชคดีที่นี่เป็นเรื่องง่ายและเพียงพอหากคุณไม่ใช้มรดกและไม่อยากส่งอีเมลธรรมดา ๆ เช่น .. :)
smido

5

หากใช้ Python 3.4+ และ Jinja2 - v2.11 + - เราสามารถรวม pathlib และ Filesystem ของ python เพื่อลดความซับซ้อนของโฟลว์

from pathlib import Path
...

p = Path(__file__).parent.parent / 'templates' # sample relative path
env = Environment(
    loader=FileSystemLoader(Path(p)))
template = env.get_template('your_file.jinja2')

ฉันไม่สะดวกในการใช้งานโดยตรงTemplate(file)เนื่องจากการประมวลผลการสืบทอดเทมเพลตของ Jinja อาจทำงานได้ไม่ดี

การรองรับ Pathlib จะถูกเพิ่มใน Jinja เวอร์ชันล่าสุด - v2.11 + เท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.