هنگام نوشتن قالبهای Jinja2، گاهی فقط میخواهیم بدانیم یک شرط، حلقه یا فیلتر با دادههای مشخص چه خروجیای تولید میکند. اجرای کل برنامه برای هر تغییر کوچک، این آزمونوخطا را طولانی میکند؛ بهخصوص وقتی فاصلهها و خطوط خالی هم در خروجی اهمیت داشته باشند.
پروژهٔ Jinja Parser یک محیط تحت وب برای همین کار است. قالب را در یک بخش مینویسید، متغیرها را به شکل JSON یا YAML وارد میکنید و نتیجه را کنار آنها میبینید. برای شروع میتوانید از دموی آنلاین استفاده کنید یا برنامه را روی سیستم خودتان اجرا کنید.
امکانات محیط آزمایش
- رندر خودکار پس از مکث کوتاه در تایپ، با امکان خاموش کردن آن و اجرای دستی از طریق دکمهٔ Render یا میانبر
Ctrl/Cmd + Enter. - دریافت متغیرها به شکل JSON یا YAML و نمایش خطاهای قالب و دادهٔ ورودی.
- نمایش اختیاری فاصلهها با علامت
•برای بررسی دقیقتر خروجی. - کپی خروجی با فاصلهها و شکست خطوط اصلی؛ علامتهای نمایشی وارد متن کپیشده نمیشوند.
- راهنمای کوتاه سینتکس Jinja2 در کنار ویرایشگرها و رابط واکنشگرا با پشتیبانی از تم روشن و تاریک.
انتخاب JSON یا YAML فقط مشخص میکند داده با چه فرمتی خوانده شود؛ تغییر این گزینه، محتوای ورودی را به فرمت دیگر تبدیل نمیکند. داده باید یک شیء JSON یا نگاشت YAML باشد، نه یک آرایه یا مقدار تکی. برای قالبی که متغیر ندارد، کافی است {} وارد کنید.
یک مثال ساده
فرض کنید میخواهید فهرست سرویسهای فعال را از روی دادهٔ ورودی بسازید. در بخش Template این قالب را قرار دهید:
Environment: {{ environment | upper }}
{% for service in services %}
{% if service.enabled %}
- {{ service.name }}: {{ service.port }}
{% endif %}
{% endfor %}
در بخش Values گزینهٔ YAML را انتخاب کرده و دادههای نمونهٔ زیر را وارد کنید:
environment: staging
services:
- name: api
port: 8080
enabled: true
- name: worker
port: 9000
enabled: false
در این مثال، نام محیط با حروف بزرگ نمایش داده میشود و فقط سرویس api در فهرست قرار میگیرد. گزینهٔ Show whitespace کمک میکند فاصلههای خروجی را ببینید و رفتار قالب را هنگام تغییر تورفتگیها بررسی کنید. برای کنترل خطوط خالی و فاصلهها نیز میتوانید از قواعد کنترل فضای خالی در Jinja2 استفاده کنید.
برنامه از StrictUndefined استفاده میکند؛ بنابراین اگر متغیری مثل environment را حذف کنید، بهجای خروجی خالی با خطا روبهرو میشوید. برای مقادیر اختیاری میتوانید مقدار جایگزین تعریف کنید:
{{ environment | default("development") }}
نصب و اجرا
اجرا با Docker
با نصب بودن Docker، سرویس را اجرا کنید:
docker run -d --name jinja-parser -p 8125:8125 hatamiarash7/jinja-parser
سپس آدرس http://localhost:8125 را در مرورگر باز کنید. در ایمیج Docker، تعداد workerهای Gunicorn بهصورت پیشفرض ۲ است و با متغیر محیطی WEB_CONCURRENCY قابل تغییر است؛ برای مثال، هنگام ساخت کانتینر گزینهٔ -e WEB_CONCURRENCY=4 را به دستور اضافه کنید.
اجرای محلی با Python
طبق راهنمای نصب پروژه، برای اجرای محلی به Python نسخهٔ ۳٫۱۳ یا جدیدتر نیاز دارید. دستورات زیر برای محیط لینوکسی با Git، Make و پشتیبانی از venv هستند:
git clone https://github.com/hatamiarash7/Jinja-Parser.git
cd Jinja-Parser
python3 -m venv .venv
make install PYTHON=.venv/bin/python
make run PYTHON=.venv/bin/python
این روش برنامه را با Gunicorn روی http://127.0.0.1:5000 اجرا میکند. پورت اجرای محلی با پورت ایمیج Docker متفاوت است. برای توسعه و بارگذاری مجدد هنگام تغییر فایلها، هدف make run-dev PYTHON=.venv/bin/python هم در دسترس است.
استفاده از API
رابط وب درخواستها را به مسیر POST /convert میفرستد. همین مسیر را میتوانید مستقیماً فراخوانی کنید. ورودی به شکل فیلدهای فرم ارسال میشود، نه بدنهٔ JSON:
curl http://localhost:8125/convert \
--data-urlencode 'template=Hello {{ name }}!' \
--data-urlencode 'type=json' \
--data-urlencode 'values={"name":"World"}' \
--data-urlencode 'whitespaces=0'
پاسخ این مثال:
{ "rendered_output": "Hello World!" }
فیلدهای template، type و values الزامیاند. مقدار type یکی از json یا yaml است و با ارسال whitespaces=1 فاصلهها در پاسخ API به • تبدیل میشوند.
نکتهٔ مهم در پیادهسازی API این است که مقدار rendered_output برای نمایش آماده میشود: کاراکترهای ویژهٔ HTML escape میشوند و شکست خطوط به <br /> تبدیل میشود. بنابراین برای مصرف خروجی در ابزارهای دیگر، آن را مستقیماً معادل یک فایل متنی خام در نظر نگیرید. رابط وب این لایهٔ نمایشی را باز میکند و نتیجه را بهصورت متن نشان میدهد؛ HTML تولیدشده اجرا نمیشود.
قالب نامعتبر، متغیر تعریفنشده یا دادهٔ ناسازگار با کد وضعیت 400 و فیلد error گزارش میشود. حجم کل بدنهٔ درخواست به ۱ مگابایت دودویی محدود است و درخواست بزرگتر پاسخ 413 میگیرد. مسیر GET /healthz هم برای بررسی زنده بودن سرویس، پاسخ {"status":"ok"} برمیگرداند.
نحوهٔ پردازش و نکات استفاده
بخش سرور با Flask نوشته شده و قالبها را در ImmutableSandboxedEnvironment مربوط به Jinja2 پردازش میکند. دادههای YAML با yaml.safe_load خوانده میشوند و متغیرهای تعریفنشده خطا ایجاد میکنند. این محیط برای آزمایش قالب و داده مناسب است؛ فیلترها و امکانات اختصاصی برنامهٔ دیگری که از Jinja2 استفاده میکند، خودبهخود در آن موجود نیستند.
قالب و متغیرها برای پردازش به سرور ارسال میشوند، پس در دموی عمومی از رمز عبور، توکن یا اطلاعات حساس استفاده نکنید. پیشنویسها هم در فضای ذخیرهسازی مرورگر ذخیره نمیشوند؛ قبل از بستن صفحه، محتوای موردنیازتان را نگه دارید.
کد پروژه با مجوز MIT منتشر شده است. جزئیات بیشتر دربارهٔ اجرا، API و توسعه در مستندات مخزن قرار دارد.