البرمجة

الدوال والمرشحات في Jinja

التعامل مع محرك القوالب Jinja: الدوال والمرشحات

يُعتبر محرك القوالب Jinja من أكثر المحركات استخداماً في بيئات تطوير تطبيقات الويب، وخصوصاً في إطار العمل Flask بلغة Python. يُمكِّن هذا المحرك المطورين من فصل منطق التطبيق عن واجهة العرض، مما يسهم في تنظيم الكود وتحسين قابلية الصيانة. يعتمد Jinja على أسلوب مشابه في البنية لمحركات القوالب الأخرى مثل Django Template Language وTwig في PHP، لكنه يتفوق في البساطة والمرونة والديناميكية.

من أهم مكونات Jinja القابلة للتخصيص والاستخدام اليومي الدوال والمرشحات (Functions & Filters)، واللتان تشكلان أدوات فعالة للتحكم بالمخرجات وعرض البيانات بالشكل المناسب. يتناول هذا المقال بالتفصيل كيفية استخدام هذه الأدوات بكفاءة داخل قوالب Jinja، مع التركيز على الجوانب التقنية المتقدمة التي تهم المطورين والمبرمجين الباحثين عن بناء واجهات ديناميكية عالية الأداء.


أساسيات محرك القوالب Jinja

قبل التعمق في الدوال والمرشحات، من الضروري تقديم لمحة تقنية موجزة عن كيفية عمل Jinja:

  • محرك Jinja يُفسر القوالب المكتوبة بلغة HTML مع شيفرات برمجية خاصة تكتب ضمن قوسين مزدوجين {{ ... }} للطباعة و{% ... %} لتنفيذ التعليمات البرمجية.

  • الترميز الآمن: يدعم Jinja الترميز التلقائي للنصوص المخرجة لمنع هجمات XSS.

  • يدعم التكرار والشروط: مثل for و if وغيرها.

  • قابلية التوسعة: يمكن إنشاء دوال ومرشحات مخصصة بسهولة.


الدوال في Jinja

أنواع الدوال

تنقسم الدوال في Jinja إلى فئتين رئيسيتين:

  1. دوال المعرفة ضمن القالب: وهي الدوال المعرفة من قبل محرك Jinja أو التي يتم تمريرها من التطبيق إلى القالب.

  2. الدوال المخصصة: وهي الدوال التي يُمكن للمطور إنشاؤها داخل التطبيق وتمريرها إلى Jinja.

استخدام الدوال في القوالب

الدوال تُستخدم داخل {{ }} لإرجاع قيمة، مثال:

jinja
{{ range(1, 5) }}

هذا المثال يطبع قائمة الأرقام من 1 إلى 4.

الدوال المدمجة (Built-in Functions)

يوفر Jinja مجموعة من الدوال الجاهزة مثل:

الدالة الوصف
range توليد قائمة من الأعداد
dict إنشاء قاموس
lipsum توليد نصوص عشوائية للاختبار
cycler توليد كائن يقوم بالدوران في قائمة من العناصر

مثال على استخدام cycler:

jinja
{% set colors = cycler('red', 'green', 'blue') %}
  • عنصر 1
  • عنصر 2
  • عنصر 3
  • إنشاء دوال مخصصة

    في إطار Flask على سبيل المثال:

    python
    def say_hello(name): return f"مرحبا، {name}!" app.jinja_env.globals.update(say_hello=say_hello)

    في القالب:

    jinja
    {{ say_hello('أحمد') }}

    المرشحات (Filters) في Jinja

    ما هي المرشحات؟

    المرشحات في Jinja هي وظائف تُطبق على البيانات المعدة للطباعة بهدف تحويلها أو تنسيقها. تُستخدم باستخدام الحرف | بعد المتغير.

    مثال:

    jinja
    {{ username|upper }}

    المرشحات المدمجة

    يحتوي Jinja على مجموعة كبيرة من المرشحات الجاهزة، ومنها:

    المرشح الوصف
    lower تحويل النص إلى أحرف صغيرة
    upper تحويل النص إلى أحرف كبيرة
    capitalize جعل أول حرف كبيرًا والبقية صغيرة
    title تحويل كل الكلمات إلى حالة العنوان
    length إرجاع عدد العناصر في متغير
    replace استبدال جزء من النص
    join دمج قائمة بعناصر محددة
    default عرض قيمة افتراضية إذا كان المتغير غير معرف
    safe عرض HTML كما هو دون ترميز
    round تقريب رقم عشري
    date تنسيق التاريخ

    مثال:

    jinja
    {{ ['أحمد', 'علي', 'منى']|join(', ') }}

    الناتج: أحمد, علي, منى


    مرشحات السلاسل النصية

    المرشحات تلعب دوراً محورياً في التعامل مع النصوص:

    • trim: لإزالة المسافات البيضاء من البداية والنهاية.

    • striptags: لإزالة الوسوم HTML من السلسلة.

    • wordcount: لعدّ عدد الكلمات في النص.

    • truncate: لاقتطاع النص لعدد معين من الحروف.

    مثال على truncate:

    jinja
    {{ long_text|truncate(100) }}

    إنشاء مرشحات مخصصة

    يمكن تعريف مرشحات جديدة بإضافة دوال إلى jinja_env.filters:

    python
    def reverse_string(value): return value[::-1] app.jinja_env.filters['reverse'] = reverse_string

    في القالب:

    jinja
    {{ 'مرحباً'|reverse }}

    الناتج: ًاحبمر


    استخدام الدوال والمرشحات معًا

    يمكن مزج الدوال والمرشحات للحصول على نتائج معقدة:

    jinja
    {{ range(1, 6)|list|join(' - ') }}

    الناتج: 1 – 2 – 3 – 4 – 5


    جداول مقارنة بين المرشحات والدوال

    العنصر الدوال (Functions) المرشحات (Filters)
    طريقة الاستخدام {{ func(args) }} `{{ value
    القابلية للتسلسل لا نعم، يمكن ربط أكثر من مرشح بسلسلة
    الهدف الرئيسي تنفيذ عمليات معقدة تنسيق أو تحويل المخرجات
    القابلية للتخصيص عالية عالية
    التداخل يمكن استخدامها داخل بعضها البعض يمكن دمجها بشكل متسلسل مع قيم متعددة

    التطبيقات العملية في مشاريع Flask

    عند استخدام Flask، فإن Jinja يأتي مدمجاً بشكل افتراضي. هذا يسمح للمطور بكتابة واجهات HTML ديناميكية دون الحاجة إلى التعامل مع تعقيدات جافاسكريبت أو معالجة البيانات على الواجهة الأمامية.

    أمثلة عملية:

    • تنسيق التاريخ داخل القالب:

      jinja
      {{ post.created_at|date("d-m-Y") }}
    • عرض نصوص قصيرة من المقالات:

      jinja
      {{ article.content|truncate(200) }}
    • استخدام دوال مخصصة لإضافة شارة (badge) بجانب اسم المستخدم بناءً على الدور:

      python
      def user_badge(role): if role == 'admin': return '🛡️' return '👤' app.jinja_env.globals.update(user_badge=user_badge)
      jinja
      {{ user_badge(user.role) }} {{ user.name }}

    استخدام مرشحات ودوال مع الحلقات الشرطية

    في حالات عرض جداول ديناميكية أو قوائم تصفية، يمكن استخدام الدوال والمرشحات داخل الحلقات:

    jinja
    {% for product in products %} {{ product.name|title }} {{ product.price|round(2) }} {{ product.description|truncate(50) }} {% endfor %}

    الأداء وتحسين الاستخدام

    • تجنب الحسابات المكثفة داخل القالب: لأن Jinja يُستخدم فقط لعرض البيانات وليس لمعالجتها.

    • تصفية HTML باستخدام safe بحذر: لتفادي الثغرات الأمنية.

    • استخدام set لتخزين نتائج العمليات المعقدة: لتفادي تكرارها عدة مرات داخل القالب.


    الخاتمة

    إن فهم كيفية استخدام الدوال والمرشحات في Jinja يمثل عنصراً حيوياً لتطوير تطبيقات ويب ديناميكية وعالية الكفاءة. فالتكامل بين منطق التطبيق وقالب العرض يُعزز من تجربة المستخدم ويسهم في كتابة كود نظيف ومنظم وسهل الصيانة. كما أن التوسع في تعريف مرشحات ودوال مخصصة يفتح آفاقاً واسعة لتخصيص طريقة عرض البيانات وتسهيل العمل الجماعي بين فرق المطورين والمصممين.


    المراجع:

    1. Jinja Official Documentation – https://jinja.palletsprojects.com

    2. Flask Official Documentation – https://flask.palletsprojects.com