البرمجة

إنشاء مرشحات Jinja في Flask

إنشاء مرشحات Jinja خاصة بك لاستخدامها في تطبيقات Flask

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


مقدمة عن Jinja ومرشحات القوالب

Jinja هو نظام قوالب (Template Engine) تم تطويره بلغة بايثون، ويُستخدم بشكل واسع مع Flask لتوليد صفحات HTML ديناميكية من خلال إدخال بيانات متغيرة يتم معالجتها داخل القالب. توفر Jinja مجموعة كبيرة من الأدوات المساعدة مثل الحلقات، الشروط، والمرشحات (Filters)، التي تسمح لك بإجراء عمليات على المتغيرات مباشرة داخل القالب.

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

مرشحات Jinja هي عبارة عن دوال تُطبق على القيم في القوالب لتغيير شكلها أو تعديلها قبل عرضها. على سبيل المثال، يمكنك استخدام المرشح |lower لتحويل النص إلى أحرف صغيرة، أو |capitalize لتحويل أول حرف من النص إلى حرف كبير. لكن في بعض الأحيان تكون المرشحات المدمجة في Jinja غير كافية لتلبية متطلبات التطبيق، لذا تسمح Jinja بإنشاء مرشحات مخصصة تناسب احتياجاتك الخاصة.


لماذا نحتاج إلى إنشاء مرشحات Jinja خاصة؟

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

  • تنسيق تواريخ بأشكال معينة تختلف عن التنسيقات الافتراضية.

  • تعديل نصوص معقدة أو تنظيفها قبل العرض.

  • تحويل قيم رقمية إلى صيغة معينة مثل عملة أو نسبة مئوية.

  • معالجة بيانات من قواعد بيانات تحتاج إلى تحليل أو تغيير معين.

إنشاء مرشحات مخصصة يجعل القوالب أكثر مرونة ونظافة، كما يتيح لك إعادة استخدام الكود بسهولة داخل القوالب المختلفة، ويقلل من التكرار في كود البايثون الخاص بالواجهة الخلفية.


كيفية إنشاء مرشح Jinja خاص في Flask

1. تعريف دالة المرشح

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

مثال بسيط على دالة تقوم بتحويل النص إلى صيغة مخصصة:

python
def reverse_string(value): return value[::-1]

في هذا المثال، الدالة reverse_string تأخذ نصًا وتُرجعه معكوسًا.

2. تسجيل المرشح داخل تطبيق Flask

بعد تعريف الدالة، تحتاج إلى تسجيلها كمرشح داخل تطبيق Flask باستخدام الكائن app.jinja_env.filters أو باستخدام الديكوريتور @app.template_filter لتكون متاحة داخل قوالب Jinja.

الطريقة الأولى:

python
app.jinja_env.filters['reverse'] = reverse_string

الطريقة الثانية:

python
@app.template_filter('reverse') def reverse_string(value): return value[::-1]

3. استخدام المرشح في القوالب

بعد تسجيل المرشح، يمكن استخدامه داخل قالب Jinja بهذه الصيغة:

jinja
{{ "Hello World!" | reverse }}

والنتيجة ستكون:

diff
!dlroW olleH

أمثلة عملية لإنشاء مرشحات Jinja مخصصة

مثال 1: تنسيق التاريخ

في كثير من التطبيقات، قد تحتاج إلى عرض التواريخ بطريقة معينة. مثلاً، تحويل تاريخ من صيغة YYYY-MM-DD إلى صيغة عربية أكثر وضوحًا.

python
from datetime import datetime @app.template_filter('format_date_ar') def format_date_ar(value, format='%d/%m/%Y'): if not value: return '' if isinstance(value, str): value = datetime.strptime(value, '%Y-%m-%d') return value.strftime(format)

في القالب:

jinja
{{ user.birthdate | format_date_ar }}

سيتم عرض التاريخ بالتنسيق العربي اليوم/الشهر/السنة.

مثال 2: تحويل الأرقام إلى صيغة العملة

يمكنك إنشاء مرشح يحول الأرقام إلى تنسيق عملة مع إضافة رمز العملة وتنسيق الفواصل.

python
@app.template_filter('currency') def currency_filter(value, symbol='ر.س'): try: value = float(value) except (ValueError, TypeError): return value return f"{symbol} {value:,.2f}"

في القالب:

jinja
{{ product.price | currency }}

مثال النتيجة: ر.س 1,250.00


التعامل مع مرشحات Jinja المتقدمة

يمكن للمرشحات المخصصة في Jinja قبول معاملات متعددة، مما يزيد من مرونتها وقدرتها على التكيف مع سيناريوهات مختلفة.

مثال: مرشح لإظهار النص بمحدد معين وعدد أحرف

python
@app.template_filter('truncate_chars') def truncate_chars(value, max_length=100, suffix='...'): if not isinstance(value, str): value = str(value) if len(value) <= max_length: return value return value[:max_length] + suffix

يمكن تمرير المعاملات داخل القالب:

jinja
{{ article.content | truncate_chars(50) }}

دمج المرشحات مع التطبيقات الكبيرة والمتعددة الملفات

في المشاريع الكبيرة التي تحتوي على ملفات متعددة، من الأفضل تنظيم المرشحات في ملف منفصل مخصص لها، ثم استيرادها في ملف التطبيق الرئيسي.

مثال:

  1. إنشاء ملف filters.py:

python
def reverse_string(value): return value[::-1] def currency_filter(value, symbol='ر.س'): try: value = float(value) except (ValueError, TypeError): return value return f"{symbol} {value:,.2f}"
  1. استيراد المرشحات وتسجيلها في app.py:

python
from flask import Flask import filters app = Flask(__name__) app.jinja_env.filters['reverse'] = filters.reverse_string app.jinja_env.filters['currency'] = filters.currency_filter

هذا الأسلوب يسهل صيانة الكود ويجعل التطبيق أكثر تنظيمًا.


نصائح عملية لتحسين استخدام مرشحات Jinja في Flask

  1. إبقاء المرشحات بسيطة ومخصصة لمهمة واحدة: تجنب إنشاء مرشحات معقدة تؤدي عدة وظائف؛ كل مرشح يجب أن يقوم بوظيفة واضحة.

  2. التأكد من معالجة الأخطاء: يجب أن يكون المرشح قادرًا على التعامل مع قيم غير متوقعة أو فارغة دون تعطل التطبيق.

  3. إعادة استخدام المرشحات في القوالب المختلفة: تجنب تكرار الكود عبر إنشاء مرشحات عامة يمكن تطبيقها في عدة أماكن.

  4. توثيق المرشحات: كتابة تعليقات واضحة لكل مرشح تشرح وظيفته والمعاملات التي يقبلها.

  5. الاختبار: اختبار المرشحات بشكل منفصل قبل استخدامها في التطبيق لتجنب الأخطاء أثناء التشغيل.


الفروق بين المرشحات والدوال المساعدة (Template Globals)

مرشحات Jinja تختلف عن الدوال المساعدة التي يمكن تسجيلها أيضًا لتُستخدم داخل القوالب. المرشحات تُستخدم لتغيير قيمة وتنسيقها، بينما الدوال المساعدة (Template Globals) تُستخدم لأداء عمليات أو إرجاع بيانات دون التغيير المباشر لقيمة معينة.


مقارنة بين مرشحات Jinja واستخدام المعالجة في بايثون

يمكن معالجة البيانات إما في الواجهة الخلفية (بايثون) أو مباشرة داخل القالب باستخدام المرشحات. لكل منهما مزايا وعيوب:

  • المعالجة في بايثون:

    • توفر تحكمًا أكبر وإمكانيات تحليلية متقدمة.

    • يمكن اختبار الكود بشكل أفضل.

    • يقلل من تعقيد القوالب.

  • المعالجة في القالب باستخدام المرشحات:

    • يُسهل تعديل طريقة العرض بسرعة.

    • يقلل الحاجة إلى تعديل الكود في الخلفية.

    • يسمح بفصل المنطق البرمجي عن واجهة المستخدم بشكل نسبي.

الأفضل هو الموازنة بين الطريقتين بحيث تبقى القوالب نظيفة والخلفية مسؤولة عن المعالجة المعقدة.


حالات استخدام شائعة للمرشحات المخصصة في Flask

الحالة وصف الاستخدام مثال عملي
تنسيق النصوص تعديل النصوص مثل التحويل إلى uppercase `{{ username
تنسيق التواريخ تحويل تاريخ إلى تنسيق معين `{{ user.created_at
تنسيق الأرقام والعملات عرض الأرقام مع فواصل وعلامات العملة `{{ product.price
تقليم النصوص قص النصوص الطويلة مع إضافة علامة القطع `{{ article.summary
التحقق من صحة البيانات تنسيق القيم الفارغة أو غير الصالحة `{{ value

تطبيق عملي كامل لإنشاء واستخدام مرشحات Jinja خاصة في Flask

فيما يلي مثال تطبيقي متكامل لإنشاء تطبيق Flask يحتوي على مرشحات مخصصة:

python
from flask import Flask, render_template from datetime import datetime app = Flask(__name__) # مرشح لتحويل النص إلى معكوسه @app.template_filter('reverse') def reverse_string(value): if not isinstance(value, str): value = str(value) return value[::-1] # مرشح لتنسيق التاريخ بصيغة عربية @app.template_filter('format_date_ar') def format_date_ar(value, format='%d/%m/%Y'): if not value: return '' if isinstance(value, str): value = datetime.strptime(value, '%Y-%m-%d') return value.strftime(format) # مرشح لتحويل الرقم إلى عملة @app.template_filter('currency') def currency_filter(value, symbol='ر.س'): try: value = float(value) except (ValueError, TypeError): return value return f"{symbol} {value:,.2f}" @app.route('/') def index(): data = { 'username': 'FlaskUser', 'birthdate': '1990-05-15', 'balance': 12345.678 } return render_template('index.html', data=data) if __name__ == '__main__': app.run(debug=True)

محتوى قالب index.html:

jinja
مرشحات Jinja مخصصة

مرحبا {{ data.username | reverse }}

تاريخ الميلاد: {{ data.birthdate | format_date_ar }}

الرصيد: {{ data.balance | currency }}

عند تشغيل التطبيق، ستلاحظ كيف تم تطبيق المرشحات المخصصة على البيانات المعروضة.


الخلاصة

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

المرشحات لا تُغني عن المعالجة الخلفية المعقدة، لكنها تكملها بتوفير واجهة سهلة وسلسة لتحويل البيانات قبل العرض، مما يؤدي إلى تحسين تجربة المستخدم وكفاءة التطوير.


المصادر والمراجع

  1. Flask Documentation – Jinja Templates

  2. Jinja2 Template Designer Documentation