اذهب إلى المحتوى

لوحة المتصدرين

  1. Ail Ahmed

    Ail Ahmed

    الأعضاء


    • نقاط

      7

    • المساهمات

      1202


  2. Mustafa Suleiman

    Mustafa Suleiman

    الأعضاء


    • نقاط

      4

    • المساهمات

      13209


  3. Buthaina Alabri

    Buthaina Alabri

    الأعضاء


    • نقاط

      3

    • المساهمات

      4


  4. Chihab Hedidi

    Chihab Hedidi

    الأعضاء


    • نقاط

      3

    • المساهمات

      2064


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 01/28/24 في كل الموقع

  1. السلام عليكم ماذ يفضل عند تعلم الرياضيات مجال تعلم الاله ماذا تنصحوني انا مركز الاول ان اتعلم الرياضيات وبعد مالخص ان اشاء الله هبتدا بادن الله تعالي كورس تعلم الاله فا في فترة تعلم الرياضيات ماذ يفضل و طباع بحل مسال برمجه علي موقع codewars بجانب كده هل يفضل ان اطور نفسي في لغة باثيون واتعلم مكتبة خاصة مجال تعلم الاله زي numpy و pandas و statistics , Matplotlib والا اي افضل ماذا تنصحوني
    2 نقاط
  2. السلام عليكم عند كاتبة الامر التالي لتحديث الpip pip install pip -U يظهر الخطاء التالي ERROR: To modify pip, please run the following command: C:\Users\Dell\AppData\Local\Programs\Python\Python312\python.exe -m pip install pip -U
    2 نقاط
  3. لأننا في كل حلقة نقوم بقسمة x على y ثم نحفظ باقي القسمة في y ونجعل x تساوي y لنبدأ حلقة جديدة وهكذا، وبناء عليه، يجب أن تستمر الحلقة التكرارية إلى أن تكون قيمة y تساوي صفرًا، لذلك الحلقة تعتمد على قيمة y وليس قيمة x مثال: نبدأ بالقيم x=15, y-10 x = 15, y = 10 # الحلقة الأولى x = 10, y = 5 # الحلقة الثانية وهي آخر حلقة لاحظ أنه في الحلقة الثانية سيدخلها وقيمة x=10 أما قيمة y=5 لذلك في نهاية الحلقة ستكون قيمة Y=0 بينما قيمة x=5 وبالتالي لن يدخل حلقة ثالثة، ويخرج ثم يطبع قيمة x=5 وهو القاسم المشترك الأكبر بين 15 و 10
    2 نقاط
  4. السلام عليكم اي هو اختبار الSAT واي علاقة الاختبار ده بل الذكاء الاصطناعي
    1 نقطة
  5. انا مشترك في دورة جافا سكربت كيف ادخل على الدورة واتابع ؟
    1 نقطة
  6. لو تحدثنا عن الأساسيات يمكن ان تستغرق المدة شهرين أو أكثر (مع التدريب وعمل مشاريع صغيرة) على حسب وقتك اليومي الذي تخصصه لهذا، الأهم ان تفهم المفاهيم الأساسية جيداً ولا تتعجل في انهاء فترة التعلم، لأن معظم عملك سيكون في إطار العمل، سأرسم لك خارطة طريق صغيرة بأهم المفاهيم التي يجب ان تركز عليها بعضها سهل وسريع الاستيعاب، وبعضها قد يستغرق منك وقتاً أطول : 1- Components تمثل الوحدة البنائية لأطر العمل والمكتبات وهذا ليس خاص ب react فقط .. فهمه وبناءه لن يكون صعباً. 2- JSX وهي عبارة عن أكواد html مدمجة داخل ملف الjs او الjsx. 3- Virtual DOM (نظري) يجب هنا فهم كيف تحسن React من سرعة واداء الموقع عبر استخدامها لل Virtual DOM. 4- State هي حالة المعلومات في تطبيقك التي تتغير عبر الوقت او اثناء حدث Event معين، وهذا مهم جداً وأساسي لبناء مكونات ديناميكية. 5- Props وهي تسمح لك بتمرير المعلومات بين component وآخر ، وهذه ميزة مهمة لتخصيص ال components وجعلها قابلة للاستخدام. 6- Lifecycle Methods وهنا يجب ان تفهم جيداً المراحل التي يمر بها ال component. 7- React Router يمثل حجر الأساس بناء تطبيقات الصفحة الواحدة SPA. 8- State Management تظهر أهميته كلما تعقد المشروع أكتر، وكثر عدد ال components، قد تواجه صعوبة في هذا الجزء حين تبدأ بالتعرف Redux او Context API ولكن مع التدريب الكافي ستتمكن من إتقانه. 9- Hooks لم تكن موجودة منذ البداية، وحين ظهرت سهلت الكثير من الأمور، وأعطت أهمية كبيرة لل Functional component، وأهمها (useState - useEffect - useContext - useReducer). 10 - Error Handling ولا تجعل هذا الأخير يخيفك كثيراً لأن React تجعل من تتبع الخطأ أمراً سهلاً. وأخيراً لا تقف بعد تعلمك لل React وتعلم بعدها إطار العمل NEXT js وهي مبنية على React، قد يصعب عليك فهم بعض المفاهيم الآن في المرحلة الحالية، لذا لا تفزع وخذ وقتك في التعلم. تمنياتي بالتوفيق
    1 نقطة
  7. اختبار SAT هو اختبار تقييمي يستخدم على نطاق واسع في الولايات المتحدة لتقييم مهارات الطلاب في مجالات متعددة، مثل الرياضيات و غيرها، حيث يطلب من الطلاب أداء مهام متنوعة في هذه المجالات، ويهدف إلى قياس إلمامهم بالمواضيع الأكاديمية ومهارات التفكير التحليلي. فيما يتعلق بالعلاقة بين اختبار SAT والذكاء الاصطناعي، يمكن استخدام التكنولوجيا والذكاء الاصطناعي في مجالات عديدة لتحسين عمليات الاختبار وتحليل النتائج. على سبيل المثال، يمكن استخدام الذكاء الاصطناعي لتطوير أسئلة اختبار ذكية ومحسّنة، وكذلك لتقديم تحليلات دقيقة لأداء الطلاب.
    1 نقطة
  8. تمام , الحمد الله اشتغل شكرااا جدااا لحضرتكم
    1 نقطة
  9. وعليكم السلام. أنت تحاول القيام بـupgrade لـpip وهذا شيء يقوم بتعديل pip نفسه. لو كنت على Linux فهذا لن يحدث مشكلا لأن Linux بإمكانه أن يكتب فوق ملفات البرنامج الذي هو قيد التشغيل، ولكن هذا غير ممكن على Windows. لذلك عليك أن تقوم بالـupgrade من خلال Python نفسه. وقد اختصر pip عليك الوقت وأعطاك الأمر الذي يجب كتابته مباشرة: C:\Users\Dell\AppData\Local\Programs\Python\Python312\python.exe -m pip install pip -U فقط جرّبه ومن المفروض أن يعمل بشكل صحيح.
    1 نقطة
  10. الخطأ الذي تواجهه يشير إلى أنه يجب تحديث pip باستخدام Python 3.12 المثبت، يمكنك تنفيذ الأمر المقترح بالدخول إلى موجه الأوامر أو تيرمينال النظام وتشغيل الأمر التالي: python -m pip install pip -U بعد تنفيذ هذا الأمر، يجب أن يتم تحديث pip إلى أحدث إصدار. يمكنك التحقق من ذلك عن طريق تشغيل: python -m pip --version
    1 نقطة
  11. السلام عليكم اذا كان لدي صفحة على المتصفح تحتوي على مربع فيه خانة اسم المستخدم و خانة كلمة المرور، كيف استطيع أن اربط صفحة الويب هذه بقاعدة البيانات التي امتلكها على SQLite
    1 نقطة
  12. إذن أنت بحاجة إلى استخدام بيئة Node.js حيث ستقوم بالتالي: تثبيت Node.js على جهازك. إنشاء المشروع من خلال أمر npm init - y ثم تثبيت المكتبات اللازمة وهما express و sqlite3 حيث sqlite3 توفر لنا الإتصال بقاعدة بيانات sqlite والتعامل معها. ثم من المفترض أن تقوم بكتابة المنطق الخاص بعملية تسجيل حساب جديد في الموقع لديك حيث ستقوم بإرسال البيانات التي أدخلها المستخدم في النموذج form إلى خادم Node.js لديك عن طريق رابط الـ API ومعالجة تلك البيانات بتخزينها في قاعدة البيانات. ثم بعد ذلك عندما يتوجه المستخدم لصفحة تسجيل الدخول نقوم بمطاقة البيانات التي سيقوم بإدخالها مع البيانات المخزنة لدينا ثم نسمح له بتصفح الموقع.
    1 نقطة
  13. انا اريد الخانة الاخيرة من الرقم A و الرقم A بين 10 أس 100000 و الصفر كيف أدخل المتغير A بأي نوع بيانات int أو long long أو double أو أيش و كيف أجيب آخر خانة ؟
    1 نقطة
  14. عفوا نسيت أن اذكر هذه المعلومة، اريدها من خلالا جافاسكريبت
    1 نقطة
  15. مرحبا هل يمكنني ان اعرف لماذا لم يتم استخدام فيجوال ستوديو كود في بداية دورة بايثون بدلا من التيرمنال حيث انه اسهل بكثير و اوضح وهل تم استعمال فيجوال استوديو كود في باقي أجزاء الدورة ام لا
    1 نقطة
  16. استخدام منفذ الأوامر هو أمر أساسي لك كمبرمج، حيث ستقوم من خلاله بتنفيذ الكثير من الأمور مثل تثبيت الحزم وتحديثها أو حذفها وإنشاء البيئة الإفتراضية وإنشاء مشروع عندما تتعلم Flask وDjango وغيرها من الأمور التي ستتعلمها أثناء تعلم البرمجة مثل رفع المشروع إلى GitHub. لذا عليك الإعتياد على التيرمنال وتخطي الشعور بالقلق عند التعامل مع الشاشة السوداء الخاصة به. وعامًة يمكنك استخدام منفذ الأوامر خلال vscode بالضغط على terminal من القائمة بالأعلى ثم اختر new terminal وهناك إختصار لفتحه وهو CTRL + ` حيث ` هو حرف ذ بالكيبورد لكن عندما تكون اللوحة باللغة الإنجليزية. وفي باقي الدورة سيتم استخدام pycharm وتستطيع استخدام vsocde إذا أردت
    1 نقطة
  17. السلام عليكم لقد قمت بإنشاء صفحة HTML لدي form ويوجد بداخله 3 عناصر <select>، وكل عنصر يحتوي على 3 اختيارات، ويتم تكرار الـ 3 اختيارات في باقي عناصر <select>، لكني اريد لو تم اختيار الإختيار الأول في عنصر <select> الأول، يقوم تلقائيًا بإخفاء العنصر الأول بين بقية العناصر. و شكرًا لكم
    1 نقطة
  18. ما فهمته هو أن لديك صفحة HTML تحتوي على نموذج (form) وثلاثة عناصر select، حيث يحتوي كل select على ثلاثة اختيارات، وعند اختيار أي اختيار في ال select، أريد أن يتم تعطيل ذلك الاختيار في ال select الباقي تلقائيًا. ويتم الأمر كالتالي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Unique Selection</title> </head> <body> <form> <select id="select1" onchange="handleSelectChange(1)"> <option value="">Select an option</option> <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select> <select id="select2" onchange="handleSelectChange(2)"> <option value="">Select an option</option> <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select> <select id="select3" onchange="handleSelectChange(3)"> <option value="">Select an option</option> <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select> </form> <script> function handleSelectChange(selectedIndex) { const selectedOption = document.getElementById(`select${selectedIndex}`).value; for (let i = 1; i <= 3; i++) { if (i !== selectedIndex) { const selectElement = document.getElementById(`select${i}`); for (let j = 0; j < selectElement.options.length; j++) { const option = selectElement.options[j]; if (option.value === selectedOption || selectedOption === "") { option.disabled = true; } else { option.disabled = false; } } } } } </script> </body> </html>
    1 نقطة
  19. انتهى الوقت قبل ان ترسل ولكن شكرا على أي حال
    1 نقطة
  20. مرحبا . فى لغة c++ لا يمكنك حفظ هذا الرقم فى متغير من نوع long long حيث ان هذا الرقم يتعدى ال 10 الاف خانة . يمكنك حفظ القيمة المدخلة ك string وليس كرقم حتى تتمكنى من حفظها فى متغير. ويمكنك الحصول على اخر خانة عن طريق هذا الكود str.substr(str.length() - 1) ويمكنك تحويلها الى int عن طريق استخدام الدالة stoi int lastDigit = stoi(str); ومن ثم طرح الرقم من 10 وهذا هو ناتج حل المسألة اما اذا كنتى تريدن حفظها فى unsigned long long فاقصى رقم يمكنك حفظه هو 18,446,744,073,709,551,615 ولتحصلى على اخر خانة يمكنك اخذ باقى قسمة الرقم على 10مثل int lastDigit = mynumber%10 ; // get last digit
    1 نقطة
  21. يمكنك استخدام نفس الأوامر الموجودة بالفيديو لرفع أي مشروع إلى GitHub كالتالي. إنشاء مستودع Git محليا للمشروع باستخدام git init. إضافة الملفات والمجلدات باستخدام git add. إضافة وصف لأول تعديل باستخدام git commit. ثم تقوم بعد ذلك إذا أردت إنشاء مستودع جديد على GitHub. ربط المستودع المحلي مع GitHub باستخدام git remote add. رفع التعديلات إلى GitHub باستخدام git push. لذا فهي نفس الخطوات بغض النظر عن نوع المشروع. فقط يجب أن تكون الملفات والمجلدات خاصة بالمشروع المراد رفعه.
    1 نقطة
  22. ما هي الخطوات لرفع التطبيق الى الاب ستور او الجوجل بلاي هل يجب رفع الداتا بيز كما نفعل في مواقع الويب ام يرجد طريقة اخرى
    1 نقطة
  23. من سيقوم بإعطائي تمارين اطبقها
    1 نقطة
  24. اسم خادم قاعدة البيانات الخاص بك، يعتمد على نوع قاعدة البيانات التي تستخدمها ونوع النظام الذي يستضيفها. يمكنك معرفة اسم خادم قاعدة البيانات الخاصة بك بعدة طرق، على حسب نوع قاعدة البيانات والنظام الذي يستضيفها. في حال استخدام قاعدة بيانات SQL مثل MySQL أو PostgreSQL أو Microsoft SQL Server، يمكنك استخدام أمر SQL مثل SELECT @@SERVERNAME; أو ابحث في ملفات إعدادات قاعدة البيانات لديك، في MySQL، على سبيل المثال، يمكنك العثور على ملف my.cnf أو my.ini الذي يحتوي على معلومات حول الخادم.
    1 نقطة
  25. كيف ارفع مشروع كالي لينكس في git
    1 نقطة
  26. عليك استخدام محرر للأكواد مثل برنامج vscode وتستطيع تحميله من هنا: https://code.visualstudio.com/sha/download?build=stable&os=win32-x64-user ومن خلال تستطيع فتح مجلد المشروع الذي ستقوم بإنشائه من خلال الخطوات المذكورة في التعليق السابق. ولفتح مجلد مشروع نقوم بالضغط على File من الأعلى ثم نختر Open Folder ثم اختر مجلد المشروع الخاص بـ Django.
    1 نقطة
  27. أشكرك كثيرا على ردك, فأنا لا امتلك الخبره في سوق العمل لذا قد افادني ردك ورسمت لي صوره عامه عن السوق ☺
    1 نقطة
  28. 1 نقطة
  29. يُعد فلاسك إطار عمل للويب مبني بلغة بايثون، ويتميز بكونه صغير الحجم وسهل المعالجة، ويوفّر أيضًا عدة أدوات وميزات من شأنها جعل إنشاء تطبيقات الويب في لغة بايثون أسهل. عند تطوير تطبيق ويب ما، من الضروري الفصل بين ما يدعى "منطق العمل business logic" و"منطق العرض presentation logic"؛ إذ يكون منطق العمل مسؤولاً عن التعامل مع طلبات المستخدمين، مُخاطبًا قاعدة البيانات لإنشاء الاستجابة المناسبة؛ في حين يُحدّد منطق العرض كيفيّة عرض البيانات للمستخدم، وذلك غالبًا باستخدام ملفات HTML لإنشاء الهيكل الأساسي لصفحة الويب التي تستجيب لطلبات المستخدمين، مع استخدام تنسيقات CSS لتنسيق مظهر تلك المكونات المبنية باستخدام HTML. فمثلًا في حال كان لدينا تطبيق للتواصل الاجتماعي، فيوجد عادةً حقلٌ لإدراج اسم المستخدم وحقل لإدراج كلمة المرور بحيث لا يظهران إلّا في حال كون المستخدم لم يسجل دخوله إلى التطبيق بعد، ولدى كتابة المستخدم اسم المستخدم وكلمة المرور يعمل فلاسك على تطبيق منطق العمل، إذ تُستخرج البيانات (اسم المستخدم وكلمة المرور) من الطلب ليُسجَّل دخول المستخدم إذا كانت هذه البيانات صحيحة، وإلّا ستظهر رسالة خطأ، ويجري التعامل مع كيفية ظهور رسالة الخطأ بالاعتماد على منطق العرض. يستخدم فلاسك محرّك القوالب جينجا jinja لبناء صفحات HTML ديناميكيًا باستخدام مفاهيم بايثون المألوفة، من متغيراتٍ وحلقاتٍ تكرارية وقوائم وغيرها، وبالتالي ستُستخدم هذه القوالب على أنها جزءٌ من هذا المشروع، إذ يُعرّف القالب بأنه ملف يحتوي على مكونات ثابتة وأُخرى ديناميكية، وعندما يطلب المستخدم عنصرًا من التطبيق، مثل الصفحة الرئيسية، أو صفحة تسجيل الدخول، يُمكنّنا جينجا من الاستجابة باستخدام قالب HTML، وبذلك يصبح من الممكن استخدام عددٍ كبيرٍ من الميزات غير المتوفرة أصلًا في لغة HTML المعيارية، مثل المتغيرات والعبارة الشرطية "if" والحلقات التكرارية مثل حلقة "for"، والمُرشّحات filters ومفهوم وراثة القوالب، إذ تسمح لنا هذه الخواص بكتابة صفحات HTML سهلة الإصلاح، كما تعزل جينجا شيفرات HTML تلقائيًا بهدف منع هجمات البرمجة العابرة للمواقع Cross-Site Scripting -أو اختصارًا XSS-. سنبني في هذا المقال تطبيق ويب صغير يعمل على تصييّر عدّة ملفات HTML ضمن المتصفح معًا، إذ سنستخدم المتغيرات لتمرير البيانات من الخادم إلى القوالب، كما سنطبّق مفهوم وراثة القوالب لتجنُّب التكرار في الشيفرات البرمجية. وسنستخدم كذلك التعابير المنطقية في بناء شيفرات القوالب من عبارات شرطية وحلقات، وسنطبّق المُرشّحات اللازمة لتعديل النصوص، وسنعمل من خلال إطار العمل بوتستراب bootstrap على إضافة التنسيقات على التطبيق ليبدو أكثر جاذبية بصريًا. مستلزمات العمل قبل المتابعة في هذا المقال لا بُدّ من: توفُّر بيئة برمجة بايثون 3 محلية، مثبّتة على حاسوبك، وسنفترض في مقالنا أن اسم مجلد المشروع هو "flask_app". توفّر إطار العمل فلاسك مُثبّت ضمن البيئة البرمجبة كما هو مُبيّن في الخطوة الأولى من المقال كيفية بناء موقعك الإلكتروني الأول باستخدام إطار عمل فلاسك Flask والإصدار الثالث من لغة بايثون. الفهم الجيد لأساسيات فلاسك، مثل مفهوم الوجهات routes ودوال العرض view في فلاسك، ويمكنك في هذا الصدد الاطلاع على المقال كيفية بناء موقعك الإلكتروني الأول باستخدام إطار عمل فلاسك Flask والإصدار الثالث من لغة بايثون المشار إليه أعلاه لفهم مبادئ فلاسك. فهم أساسيات لغة HTML. الخطوة الأولى - تصيير القوالب واستخدام المتغيرات بعد التأكّد من تفعيل بيئة البرمجة وتثبيت فلاسك، سنبدأ ببناء التطبيق، إذ تتمثّل الخطوة الأولى بعرض رسالة ترحيب بالزوار في الصفحة الرئيسية، وسنستخدم لهذا الغرض دالة فلاسك المساعدة ()render_template لتوفير قوالب HTML مثل استجابة ضمن الصفحة، وسنتعلّم في هذا الصدد كيفيّة تمرير المتغيرات من التطبيق إلى القوالب. بدايةً نفتح الملف "app.py" الموجود في المجلد "flask_app" لتعديله وذلك باستخدام محرّر النصوص نانو "nano" أو أي محرر آخر تفضّله: (env) user@localhost:$ nano app.py ونضيف الشيفرة التالية ضمنه: from flask import Flask, render_template app = Flask(__name__) @app.route('/') def hello(): return render_template('index.html') نحفظ الملف ونغلقه. استوردنا في الشيفرة السابقة الصنف Flask الذي سنستخدمه لإنشاء نسخة من تطبيق باسم "app"، كما استوردنا الدالة ()render_template من حزمة flask، ثمّ عرفنا دالة العرض ()hello (وهي في الواقع دالة بايثون اعتيادية تعيد استجابةً من النمط HTTP) باستخدام المُزخرف ()app.route، الذي يحوّل دوال بايثون الاعتيادية إلى دوال عرض في فلاسك، تستخدم دالة العرض هذه الدالة ()render_template لتصييّر ملف قالب HTML المُسمّى "index.html". الآن، سننشئ القالب "index.html" ضمن المجلد الفرعي "templates" من المجلد الرئيسي "flask_app"، إذ سيبحث فلاسك عن القوالب في المجلد المسمّى "templates" تحديدًا، لذا يُعدُّ الاسم مهمًا. لإنشاء هذا المجلد، نتأكد من وجودنا ضمن المجلد "flask_app" وننفذ الأمر التالي: (env) user@localhost:$ mkdir templates بعد ذلك، ننشئ ملفًا باسم "index.html" ضمن مجلد القوالب "templates" لنكتب ضمنه لاحقًا الشيفرات اللازمة، ومن الجدير بالملاحظة أنّه من غير الضروري التقيُّد باسم "index.html" على عكس اسم المجلد الرئيسي، فمن الممكن تغييّر اسم الملف ليصبح مثلًا "home.html"، أو "homepage.html"، أو أي اسم آخر تفضّله: (env) user@localhost:$ nano templates/index.html ثمّ نضيف شيفرة HTML التالية داخل الملف "index.html": <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>FlaskApp</title> </head> <body> <h1>Hello World!</h1> <h2>Welcome to FlaskApp!</h2> </body> </html> اخترنا في الشيفرة السابقة عنوانًا للصفحة، كما أضفنا الرسالة "!Hello World" لتظهر ضمن تنسيق عنوان من المستوى الأوّل H1، والرسالة "!Welcome to FlasApp" لتظهر ضمن تنسيق عنوان من المستوى الثاني H2. نحفظ الملف ونغلقه. ولتشغيل تطبيق الويب الذي أنشأناه، وبعد التأكّد من وجودنا ضمن المجلد "flask_app" مع تفعيل البيئة الافتراضية، لا بُدّ من إرشاد فلاسك إلى موقع التطبيق (في حالتنا الملف ذو الاسم app.py) باستخدام متغير بيئة فلاسك FLASK_APP، ولتشغيله بوضع التطوير، نضبط متغير بيئة فلاسك Flask_ENV على الوضع development على النحو التالي (مع ملاحظة أنّنا نستخدم الأمر set في بيئة ويندوز عوضًا عن الأمر export): (env) user@localhost:$ export FLASK_APP=app (env) user@localhost:$ export FLASK_ENV=development بعدها سنشغل التطبيق باستخدام الأمر flask run: (env) user@localhost:$ flask run بعد التأكد من كون خادم التطوير ما يزال قيد التشغيل، نذهب إلى الرابط التالي باستخدام المتصفح: http://127.0.0.1:5000/ فتظهر العبارة "FlasApp" عنوانًا للصفحة، ويجري تصييّر الرسالتين المكتوبتين في HTML لتظهرا بالتنسيق المطلوب. تُمرّر البيانات عادةً في تطبيقات الويب من ملفات بايثون الخاصة بالتطبيق إلى قوالب HTML، ولنوضّح كيفية فعل ذلك في تطبيقنا هذا، سنمرّر متغيرًا يحتوي على التاريخ والوقت وفق التوقيت العالمي UTC إلى القالب الرئيسي، وبعدها سنعرض قيمة هذا المتغير في القالب. سنترك خادم التطوير قيد التشغيل وسنفتح الملف app.py في نافذة أسطر أوامر جديدة للتعديل عليه: (env) user@localhost:$ nano app.py سنستورد الوحدة الخاصّة بالتعامل مع الوقت والتاريخ datetime من مكتبة بايثون المعيارية وسنعدّل الدالة ()index ليبدو الملف كما يلي: import datetime from flask import Flask, render_template app = Flask(__name__) @app.route('/') def hello(): return render_template('index.html', utc_dt=datetime.datetime.utcnow()) نحفظ الملف ونغلقه. استوردنا في الشيفرة السابقة الوحدة datetime ومرّرنا المتغير المُسمّى utc_dt مع قيمة ()datetime.datetime.utcnow التي تمثّل الوقت والتاريخ الحالي وفق التوقيت العالمي إلى القالب "index.html". ولعرض قيمة هذا المتغير في الصفحة الرئيسية، سنفتح الملف index.html من أجل التعديل عليه: (env) user@localhost:$ nano templates/index.html وسنعدّل الملف كما يلي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>FlaskApp</title> </head> <body> <h1>Hello World!</h1> <h2>Welcome to FlaskApp!</h2> <h3>{{ utc_dt }}</h3> </body> </html> نحفظ الملف ونغلقه. أضفنا موضعًا لنص منسّق مثل عنوان من المستوى الثالث H3 مع استخدام المُحدّد الخاص "{{ … }}" لطباعة قيمة المتغيّر utc_dt ضمنه. الآن، بالذهاب إلى صفحة التطبيق الرئيسية ضمن المتصفح: http://127.0.0.1:5000/ ستظهر صفحة مشابهة للصورة التالية: ومع نهاية هذه الخطوة نكون قد أنشأنا صفحةً رئيسيةً ذات قالب HTML داخل تطبيق فلاسك، وصيّرنا محتويات قالب آخر، ومرّرنا وأظهرنا قيمة مُتغير، وفيما يلي سنتجنّب تكرار الشيفرات البرمجية باستخدام مفهوم وراثة القوالب. الخطوة الثانية – استخدام مفهوم وراثة القوالب سننشئ في هذه الخطوة قالبًا أساسيًا ذا محتوًى قابل للمشاركة مع القوالب الأُخرى، وسنعدّل قالب الصفحة الرئيسية index template للتطبيق ليرث من القالب الأساسي هذا، ثمّ سننشئ صفحةً جديدةً مسؤولةً عن عرض معلومات التطبيق للمستخدمين. يحتوي القالب الأساسي على أهم مكونات HTML المُستخدمة عادةً في أي قالب، مثل عنوان التطبيق وأشرطة التنقّل والتذييلات. بدايةً، سننشئ ملفًا جديدًا باسم "base.html" ضمن مجلد القوالب templates: (env) user@localhost:$ nano templates/base.html وسنكتب ضمنه الشيفرات التالية: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %} {% endblock %} - FlaskApp</title> <style> nav a { color: #d64161; font-size: 3em; margin-left: 50px; text-decoration: none; } </style> </head> <body> <nav> <a href="#">FlaskApp</a> <a href="#">About</a> </nav> <hr> <div class="content"> {% block content %} {% endblock %} </div> </body> </html> نحفظ الملف ونغلقه. الجزء الأكبر من الشيفرة السابقة هو تعليمات HTML معيارية تشمل عنوانًا وبعض التنسيقات لروابط التنقل، إضافةً إلى شريط تنقّل مع رابطين، أحدهما للوصول إلى الصفحة الرئيسية للتطبيق والآخر للوصول إلى صفحة المعلومات التي لم ننشئها بعد، إضافةً إلى عنصر الحافظة <div> ليتضمّن محتويات الصفحة. لا تعمل هذه الروابط بعد لكننا سنوضح في الخطوة التالية كيفية إنشاء الربط بين الصفحات. أمّا الأجزاء من الشيفرة الموضحّة فيما يلي فهي خاصةٌ بمحرك القوالب جينجا: {% block title %} {% endblock %}: كتلة برمجية تحجز مكانًا لعنوان الصفحة، الذي سنستخدمه لاحقًا في تحديد العنوان الخاص بكل صفحة في التطبيق دون الحاجة إلى إعادة كتابة قسم الترويسة <head> كاملًا في كل مرةٍ من أجل كل صفحة. {% block content %} {% endblock %}: كتلة برمجية أخرى ستُستبدل لاحقًا بالمحتوى الفعلي بالاعتماد على القالب الابن، أي القالب الذي يرث شيفرات القالب الرئيسي "base.html". والآن، بعد أن أصبح لديك قالبٌ رئيسي، يمكنك الاستفادة من ميزاته باستخدام فكرة الوراثة، لذلك افتح الملف "index.html": (env) user@localhost:$ nano templates/index.html ثمّ استبدل محتوياته بما يلي: {% extends 'base.html' %} {% block content %} <h1>{% block title %} Index {% endblock %}</h1> <h1>Hello World!</h1> <h2>Welcome to FlaskApp!</h2> <h3>{{ utc_dt }}</h3> {% endblock %} استخدمنا في هذه النسخة الجديدة من القالب template.html الوسم {% extends %} للوراثة من القالب الرئيسي base.html، وذلك عن طريق استبدال الشيفرة السابقة بكتلة المحتوى content في القالب الرئيسي. تحوي كتلة المحتوى هذه على وسم <h1> وبداخله كتلة عنوان title تحتوي على العبارة "Index"، والتي بدورها تستبدل كتلة العنوان title الموجودة أصلًا في القالب الرئيسي base.html لتحتوي على العبارة "Index" وبذلك يصبح العنوان كاملًا "Index - FlaskApp"، وبهذه الطريقة نتفادى تكرار نفس النص مرتين، ذلك لأنّ هذا النص سيظهر في عنوان الصفحة وضمن الوسم <h1> أسفل شريط التصفح الموروث من القالب الرئيسي. وبذلك يصبح لدينا عدة عناوين، الأوّل بتنسيق من المستوى الأوّل <h1> يتضمّن النص "!Hello World"، والثاني بتنسيق من المستوى الثاني <h2>، والثالث بتنسيق من المستوى الثالث <h3> والذي يحتوي على قيمة متغير الوقت والتاريخ utc_dt. تمكنّنا وراثة القوالب من إعادة استخدام شيفرة HTML الموجودة في القوالب الأخرى (القالب الرئيسي base.html في حالتنا) دون الحاجة لتكراره في كل مرة. اِحفظ الملف وأغلقه، ثم حدِّث الصفحة الرئيسية index في المتصفح، فستظهر الصفحة بشريط تصفح وعنوانٍ منسقٍ كما يلي: أمّا الآن فسننشئ صفحة معلومات التطبيق، لذا سنفتح الملف "app.py" ولنضيف ضمنه وجهةً جديدةً: (env) user@localhost:$ nano app.py ونضيف الوجهة التالية إلى نهايته: # ... @app.route('/about/') def about(): return render_template('about.html') استخدمنا المزخرف ()app.route لإنشاء دالة فلاسك باسم "()about"، إذ ترجع ضمنها نتيجة استدعاء الدالة ()render_template لدى تمرير اسم ملف القالب "about.html" وسيطًا لها. نحفظ الملف ونغلقه. الآن سننشئ ملف قالب باسم "about.html" كما يلي: (env) user@localhost:$ nano templates/about.html ونضيف ضمنه الشيفرة التالية: {% extends 'base.html' %} {% block content %} <h1>{% block title %} About {% endblock %}</h1> <h3>FlaskApp is a Flask web application written in Python.</h3> {% endblock %} استخدمنا في الشيفرة السابقة الوسم extend لوراثة الشيفرات من القالب الرئيسي، كما استبدلنا كتلة المحتوى content في القالب الرئيسي بوسم من النوع <h1> الذي يعمل أيضًا بمثابة عنوان للصفحة، وأضفنا بعض المعلومات حول التطبيق ضمن وسم من النوع <h3>. نحفظ الملف ونغلقه. بعد التأكد من أنّ خادم التطوير ما يزال قيد التشغيل، ننتقل إلى الرابط التالي باستخدام المتصفح: http://127.0.0.1:5000/about فتظهر صفحةٌ مشابهة للصورة التالية: نلاحظ وراثة شريط التنقل وجزءٍ من العنوان من القالب الأساسي. ومع نهاية هذه الخطوة نكون قد أنشأنا قالبًا أساسيًا واستخدمناه في بناء صفحة التطبيق الرئيسية وصفحة معلومات التطبيق لتجنُّب تكرار الشيفرات، إلّا أنّ الروابط في شريط التنقل ما تزال غير مُفعّلة ولا تؤدي أية مهمة حتى الآن، لذا سنربط في الخطوة سنربط بين الوجهات في القوالب من خلال تعديل الروابط في شريط التنقل. الخطوة الثالثة – الربط بين الصفحات سنتعلّم في هذه الخطوة كيفيّة الربط بين الصفحات باستخدام الدالة المساعدة ()url_for، إذ سنضيف رابطين إلى شريط التنقل في القالب الأساسي، أحدهما للوصول إلى الصفحة الرئيسية والآخر للوصول إلى صفحة معلومات التطبيق. بدايةً سنفتح القالب الأساسي لتعديله: (env) user@localhost:$ nano templates/base.html ونعدّل الملف كما يلي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %} {% endblock %} - FlaskApp</title> <style> nav a { color: #d64161; font-size: 3em; margin-left: 50px; text-decoration: none; } </style> </head> <body> <nav> <a href="{{ url_for('hello') }}">FlaskApp</a> <a href="{{ url_for('about') }}">About</a> </nav> <hr> <div class="content"> {% block content %} {% endblock %} </div> </body> </html> استخدمنا في الشيفرة السابقة دالة ()url_for خاصّة، والتي ستُعيد الرابط الموافق لدالة فلاسك المُمرّرة لها، إذ أنّ الرابط الأول مرتبط بالوجهة الخاصة بدالة فلاسك ()hello (وهي الصفحة الرئيسية للتطبيق)، في حين يرتبط الرابط الثاني بالوجهة الخاصة بدالة فلاسك ()about، مع ملاحظة أنّنا مرّرنا اسم دالة فلاسك وسيطًا وليس اسم الوجهة (/ أو about/). يساعد استخدام الدالة ()url_for لبناء الروابط على إدارتها على نحوٍ أفضل، فلو كتبنا الروابط بصورةٍمحددة وبتعليمات برمجية ثابتة فإنها ستفشل مع أول تعديل على الوجهات، في حين أنّه ومع استخدام الدالة ()url_for فمن الممكن التعديل على الوجهات مع ضمان محافظة الروابط على عملها الطبيعي المتوقع، ناهيك عن كون دالة ()url_for مسؤولة أيضًا عن أمور أُخرى مثل عزل المحارف الخاصة. نحفظ الملف ونغلقه. سنعود الآن إلى الصفحة الرئيسية ونجرّب الروابط الموجودة في شريط التنقل، فنجد أنها تعمل كما هو مطلوب. ومع نهاية هذه الخطوة نكون قد تعلمنا كيفية استخدام الدالة ()url_for للربط بين الوجهات في القوالب، وفيما يلي سنضيف بعض العبارات الشرطية للتحكم بما يُعرض في القوالب بناءً على الشروط التي نضعها، كما سنستخدم حلقات "for" التكرارية في قوالبنا لعرض عناصر القائمة. الخطوة الرابعة - استخدام العبارات الشرطية والحلقات التكرارية سنستخدم في هذه الخطوة العبارة الشرطية "if" في القوالب للتحكم بما سيُعرض بناءً على شروط محدّدة، كما سنستخدم حلقات "for" التكرارية للتنقّل بين عناصر قوائم بايثون وعرضها، ثمّ سنضيف صفحةً جديدةً إلى التطبيق مهمتها عرض التعليقات ضمن قائمة، بحيث تكون التعليقات ذات رقم الدليل الزوجي بخلفية زرقاء والتعليقات ذات رقم الدليل الفردي بخلفية رمادية. سننشئ بدايةً وجهةً جديدةً لصفحة التعليقات، لذا سنفتح الملف app.py للتعديل عليه: (env) user@localhost:$ nano app.py ونضيف الوجهة التالية إلى نهاية الملف: # ... @app.route('/comments/') def comments(): comments = ['This is the first comment.', 'This is the second comment.', 'This is the third comment.', 'This is the fourth comment.' ] return render_template('comments.html', comments=comments) لدينا في الوجهة السابقة قائمة مبنية في بايثون باسم comments تحتوي على أربعة عناصر (في التطبيق العملي يمكن الحصول على هذه التعليقات من قاعدة البيانات بدلاً من كتابتها يدويًا وتثبيتها ضمن الشيفرة)، لتكون القيمة المعادة هي تصيّير لملف قالب باسم "comments.html" وذلك في السطر الأخير من الشيفرة، ممررين المتغير comments الذي يحتوي القائمة مثل وسيط إلى ملف القالب. نحفظ الملف ونغلقه. بعدها ننشئ ملف جديد باسم comments.html ضمن مجلد القوالب templates للتعديل عليه: (env) user@localhost:$ nano templates/comments.html ونضيف ضمنه الشيفرة التالية: {% extends 'base.html' %} {% block content %} <h1>{% block title %} Comments {% endblock %}</h1> <div style="width: 50%; margin: auto"> {% for comment in comments %} <div style="padding: 10px; background-color: #EEE; margin: 20px"> <p style="font-size: 24px">{{ comment }}</p> </div> {% endfor %} </div> {% endblock %} وفيه توسعنا بالقالب الأساسي base.html واستبدلنا محتويات كتلة المحتوى content. واستخدمنا تنسيق عنوان من النمط <h1> الذي سيعمل أيضًا بمثابة عنوانٍ للصفحة. كما استخدما حلقة for التكرارية وهي من ضمن تعليمات محرّك القوالب جينجا وذلك في السطر البرمجي {% for comment in comments %} بهدف التنقل بين التعليقات في القائمة comments المُخزنة ضمن المتغير المسمّى comment، إذ سنعرض التعليقات باستخدام الوسم <p style="font-size: 24px">{{ comment }}</p>، أي بنفس الآلية التي يُعرض فيها أي متغير في جينجا، مع ملاحظة أنّ نهاية حلقة for هنا تكون باستخدام الكلمة المفتاحية {% endfor %} الأمر المختلف عن طريقة بناء حلقات for في بايثون. نحفظ الملف ونغلقه. الآن وبعد التأكد من كون خادم التطوير ما يزال قيد التشغيل، نفتح المتصفح وننتقل إلى صفحة التعليقات باستخدام الرابط: http://127.0.0.1:5000/comments فتظهر الصفحة بما يشبه التالي: الآن سنستخدم عبارة if الشرطية في القوالب لعرض التعليقات ذات رقم الدليل الفردي بخلفية رمادية والتعليقات ذات رقم الدليل الزوجي بخلفية زرقاء. لذا سنفتح ملف القالب comments.html: (env) user@localhost:$ nano templates/comments.html ثمّ سنعدله ليصبح كما يلي: {% extends 'base.html' %} {% block content %} <h1>{% block title %} Comments {% endblock %}</h1> <div style="width: 50%; margin: auto"> {% for comment in comments %} {% if loop.index % 2 == 0 %} {% set bg_color = '#e6f9ff' %} {% else %} {% set bg_color = '#eee' %} {% endif %} <div style="padding: 10px; background-color: {{ bg_color }}; margin: 20px"> <p>#{{ loop.index }}</p> <p style="font-size: 24px">{{ comment }}</p> </div> {% endfor %} </div> {% endblock %} وفي هذا التعديل أضفنا عبارة if الشرطية في السطر {% if loop.index % 2 == 0 %}، إذ أنّ المتغير loop هو متغير خاص في جينجا يمكنّنا من الوصول إلى معلومات حول الحلقة الحالية، واستخدمنا loop.index للحصول على دليل العنصر الحالي، الذي يبدأ من "1" وليس من "0" كما هو الحال في قوائم بايثون. تتحقق عبارة if ما إذا كان الدليل زوجياً باستخدام عملية باقي القسمة %، إذ تُفحص قيمة باقي قسمة الدليل على الرقم "2"، فإذا كان الباقي يساوي "0"، فهذا يعني أن الدليل زوجي، وإلّا فيكون الدليل فرديًا. استخدمنا الوسم {% set %} للتعريف عن متغير باسم bg_color ليتضمّن لون الخلفية المطلوب، فإذا كان الدليل زوجيًا، نضبط قيمة هذا المتغير إلى اللون الأزرق، وإلّا وفي حال كون الدليل فرديًا نضبطها إلى اللون الرمادي، ثم نخصّص المتغير bg_color لضبط لون الخلفية للوسم <div> الحاوي على التعليق. نستخدم loop.index في أعلى النص الخاص بالتعليق لعرض رقم الدليل الحالي ضمن وسمٍ من النوع <p>. نحفظ الملف ونغلقه. الآن بفتح المتصفح والانتقال إلى صفحة التعليقات كما يلي: http://127.0.0.1:5000/comments ستظهر صفحة التعليقات الجديدة كما في الصورة: وضّحنا فيما سبق كيفية استخدام العبارة الشرطية if، ولكن من الممكن الحصول على نفس النتيجة باستخدام الدالة الخاصّة المساعدة ()loop.cycle في جينجا، ولتوضيح هذه النقطة سنفتح الملف "comments.html": (env) user@localhost:$ nano templates/comments.html ونعدله ليصبح كما يلي: {% extends 'base.html' %} {% block content %} <h1>{% block title %} Comments {% endblock %}</h1> <div style="width: 50%; margin: auto"> {% for comment in comments %} <div style="padding: 10px; background-color: {{ loop.cycle('#EEE', '#e6f9ff') }}; margin: 20px"> <p>#{{ loop.index }}</p> <p style="font-size: 24px">{{ comment }}</p> </div> {% endfor %} </div> {% endblock %} حذفنا في هذه الشيفرة العبارة الشرطية "if/else" واستخدمنا عوضًا عنها الدالة المساعدة ('loop.cycle('#EEE', '#e6f9ff للتنقل بين اللونين، إذ ستكون قيمة المتغيّر background-color مساويةً للقيمة "‎#EEE" للون الرمادي مرّةً، ثمّ تتحول إلى القيمة "‎#e6f9ff" للون الأزرق مرةً أُخرى، وهكذا بالتناوب. نحفظ الملف ونغلقه. لدى فتح صفحة التعليقات في المتصفح وتحديثها، ستظهر صفحةٌ مشابهةٌ لتلك التي ظهرت مع استخدام عبارة "if" الشرطية. يمكن استخدام عبارات "if" الشرطية لأغراض مختلفة، بما في ذلك التحكم بما يُعرض على الصفحة، فعلى سبيل المثال لعرض جميع التعليقات باستثناء التعليق الثاني، يمكننا استخدام عبارة if بالشرط loop.index != 2 لترشيح التعليق الثاني. لذا سنفتح قالب التعليقات: (env) user@localhost:$ nano templates/comments.html ونعدله ليصبح كما يلي: {% extends 'base.html' %} {% block content %} <h1>{% block title %} Comments {% endblock %}</h1> <div style="width: 50%; margin: auto"> {% for comment in comments %} {% if loop.index != 2 %} <div style="padding: 10px; background-color: #EEE; margin: 20px"> <p>#{{ loop.index }}</p> <p style="font-size: 24px">{{ comment }}</p> </div> {% endif %} {% endfor %} </div> {% endblock %} استخدمنا العبارة الشرطية {‎% if loop.index != 2 %‎} لعرض التعليقات ذات رقم الدليل غير المساوي للرقم "2"، ما يشمل جميع التعليقات باستثناء التعليق الثاني، كما استخدمنا شيفرةً ثابتةً لتغيير لون الخلفية بدلًا من استخدام الدالة المساعدة ()loop.cycle لتسهيل الأمور، أمّا بالنسبة لبقية أجزاء الشيفرة، فلم نجري عليها أي تغييرات، وأيضًا هنا تُنهى عبارة if الشرطية باستخدام الأمر {% endif %}. نحفظ الملف ونغلقه. سنلاحظ بتحديث صفحة التعليقات عدم ظهور التعليق الثاني. سنضيف الآن رابط يسمح للمستخدم بالانتقال إلى صفحة التعليقات مباشرةً من شريط التنقل، لذا سنفتح القالب الأساسي للتعديل عليه: (env) user@localhost:$ nano templates/base.html وسنعدّل محتويات الوسم <nav> بإضافة رابط جديد <a> إليه كما يلي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %} {% endblock %} - FlaskApp</title> <style> nav a { color: #d64161; font-size: 3em; margin-left: 50px; text-decoration: none; } </style> </head> <body> <nav> <a href="{{ url_for('hello') }}">FlaskApp</a> <a href="{{ url_for('comments') }}">Comments</a> <a href="{{ url_for('about') }}">About</a> </nav> <hr> <div class="content"> {% block content %} {% endblock %} </div> </body> </html> استخدمنا الدالة المساعدة ()url_for للوصول إلى دالة فلاسك ()comments نحفظ الملف ونغلقه. وبذلك أصبح شريط التنقل يحتوي على رابط جديد ينقل المستخدم إلى صفحة التعليقات مباشرةً. وبذلك نكون قد تعلمنا كيفية استخدام العبارة الشرطية "if" في القوالب للتحكّم بما يُعرَض وفقًا لشروط معينة، كما استخدمنا حلقات "for" التكرارية للتنقل بين عناصر قوائم بايثون وعرض كل منها، وتعلمنا كيفية استخدام المتغير "loop" الخاص في جينجا، وسنستخدم في الخطوة التالية مرشّحات جينجا للتحكّم بكيفية عرض بيانات المتغير. الخطوة 5 – استخدام المرشحات سنتعلّم في هذه الخطوة كيفيّة استخدام مُرشحات جينجا في القوالب، إذ سنستخدم المُرشّح upper لتحويل كامل نصوص التعليقات التي أضفناها في الخطوة السابقة (أو الواردة من قاعدة البيانات في الواقع العملي) إلى حالة أحرف كبيرة، في حين سنستخدم المرشح join لربط عدّة سلاسل نصيّة لتصبح سلسلةً واحدة، كما سنتعرّف على كيفيّة تصيّير شيفرة HTML موثوقة وآمنة دون الحاجة لعزلها باستخدام المرشح safe. بدايةً سنعمل على تحويل التعليقات في صفحة التعليقات إلى حالة الأحرف الكبيرة، لذا سنفتح القالب "comments.html" للتعديل عليه: (env) user@localhost:$ nano templates/comments.html ثمّ سنعدله ليصبح كما يلي: {% extends 'base.html' %} {% block content %} <h1>{% block title %} Comments {% endblock %}</h1> <div style="width: 50%; margin: auto"> {% for comment in comments %} {% if loop.index != 2 %} <div style="padding: 10px; background-color: #EEE; margin: 20px"> <p>#{{ loop.index }}</p> <p style="font-size: 24px">{{ comment | upper }}</p> </div> {% endif %} {% endfor %} </div> {% endblock %} أضفنا مرشح upper باستخدام رمز | الذي يمثل أنبوبًا pipe، والذي سيعمل على تعديل قيمة متغير comment إلى حالة الأحرف الكبيرة. نحفظ الملف ونغلقه. وبعد التأكد من كون خادم التطوير ما يزال قيد التشغيل، ننتقل إلى صفحة التعليقات باستخدام المتصفح: http://127.0.0.1:5000/comments ونلاحظ أنّ جميع التعليقات أصبحت في حالة الأحرف الكبيرة بعد تطبيق المرشح، كما من الممكن تمرير وسطاء للمُرشّحات بين أقواسها. لتوضيح هذه النقطة: سنستخدم المُرشّح join لدمج جميع التعليقات الموجودة في القائمة comments ضمن سلسلة واحدة. لذا سنفتح قالب التعليقات: (env) user@localhost:$ nano templates/comments.html ونعدله كما يلي: {% extends 'base.html' %} {% block content %} <h1>{% block title %} Comments {% endblock %}</h1> <div style="width: 50%; margin: auto"> {% for comment in comments %} {% if loop.index != 2 %} <div style="padding: 10px; background-color: #EEE; margin: 20px"> <p>#{{ loop.index }}</p> <p style="font-size: 24px">{{ comment | upper }}</p> </div> {% endif %} {% endfor %} <hr> <div> <p>{{ comments | join(" | ") }}</p> </div> </div> {% endblock %} أضفنا في الشيفرة السابقة الوسم <hr> (الذي يُصيّر مثل فاصل أفقي)، والوسم <div> (الذي يُستخدم لأغراض التنسيق وتجميع العناصر)، إذ دمجنا جميع التعليقات الموجودة في القائمة comments باستخدام المُرشّح ()join. نحفظ الملف ونغلقه. وبتحديث صفحة التعليقات ستظهر كما يلي: نلاحظ عرض كافّة محتويات القائمة comments بحيث تكون التعليقات مفصولة عن بعضها برمز الشريط العمودي pipe وهي القيمة المُمررة وسيطًا إلى المُرشّح ()join. ومن المُرشّحات المهمّة الأُخرى المُرشّح safe الذي يساعد في تصيّير شيفرة HTML موثوقة في المتصفح، ولتوضيح ذلك سنضيف نصًا يحتوي على وسم HTML ما إلى قالب التعليقات (لنرى هل سيُصيّر في المُتصفّح أم سيُعامل على أنه نص عادي) باستخدام مُحدّد جينجا "{{ }}". نحصل في التطبيق العملي على هذا النص (التعليق) مثل متغير آتٍ من الخادم، ومن ثمّ سنعدّل وسيط المُرشّح ()join ليكون وسم <hr> (أي الفصل بين التعليقات بشريط أفقي) بدلًا من الشريط العمودي pipe. لذا سنفتح قالب التعليقات: (env) user@localhost:$ nano templates/comments.html ونعدّله ليصبح كما يلي: {% extends 'base.html' %} {% block content %} <h1>{% block title %} Comments {% endblock %}</h1> <div style="width: 50%; margin: auto"> {% for comment in comments %} {% if loop.index != 2 %} <div style="padding: 10px; background-color: #EEE; margin: 20px"> <p>#{{ loop.index }}</p> <p style="font-size: 24px">{{ comment | upper }}</p> </div> {% endif %} {% endfor %} <hr> <div> {{ "<h1>COMMENTS</h1>" }} <p>{{ comments | join(" <hr> ") }}</p> </div> </div> {% endblock %} أضفنا القيمة <h1>COMMENTS</h1> وغيرنا وسيط مُرشّح الدمج ليصبح وسم <hr>. نحفظ الملف ونغلقه. وبتحديث صفحة التعليقات تظهر صفحةٌ مشابهةٌ لما يلي: نلاحظ أنّ وسوم HTML التي أضفناها ضمن التعليقات لم تُصيَّر، وهي ميزة أمان مهمّة في جينجا، لأنّ وسوم HTML قد تكون ضارة أو خبيثة، ويمكن أن تؤدي إلى هجمات البرمجة العابرة للمواقع XSS. أمّا لتصيير وسوم HTML المُضافة السابقة نفتح ملف قالب التعليقات: (env) user@localhost:$ nano templates/comments.html ونعدله بإضافة المُرشّح safe، للدلالة على أنّ هذه الوسوم آمنة ونريد تصييّرها: {% extends 'base.html' %} {% block content %} <h1>{% block title %} Comments {% endblock %}</h1> <div style="width: 50%; margin: auto"> {% for comment in comments %} {% if loop.index != 2 %} <div style="padding: 10px; background-color: #EEE; margin: 20px"> <p>#{{ loop.index }}</p> <p style="font-size: 24px">{{ comment | upper }}</p> </div> {% endif %} {% endfor %} <hr> <div> {{ "<h1>COMMENTS</h1>" | safe }} <p>{{ comments | join(" <hr> ") | safe }}</p> </div> </div> {% endblock %} نلاحظ أنّه من الممكن ربط المُرشّحات كما هو ظاهر في السطر: <p>{{ comments | join(" <hr> ") | safe }}</p> إذ يُطبَّق كل مُرشّح على نتيجة خرج المُرشّح السابق له. نحفظ الملف ونغلقه. وبتحديث صفحة التعليقات نجد أن وسوم HTML قد جرى تصييّرها كما هو مُتوقّع مع استخدام المُرشّح "safe": تنبيه: قد يجعل تطبيق المُرشّح "safe" لشيفرة HTML غير موثوقة المصدر تطبيقنا عرضةً لهجمات البرمجة عابرة المواقع، لذا لا يُفضّل استخدامه إلّا إذا كانت شيفرات HTML المُراد تصييّرها موثوقة المصدر. تعرّفنا في هذه الخطوة على كيفيّة استخدام المُرشّحات في قوالب جينجا لتعديل قيم المتغيرات، وفيما يلي سنستخدم حزمة بوتستراب Bootstrap لتنسيق مظهر التطبيق وجعله أكثر جاذبية بصريًا. الخطوة السادسة – استخدام بوتستراب سنتعرّف في هذه الخطوة على كيفيّة استخدام حزمة بوتستراب لتنسيق مظهر التطبيق، إذ سنضيف شريط تنقّل في القالب الأساسي بحيث يظهر في كافّة الصفحات التي ترث شيفراتها منه. يساعد إطار العمل بوتستراب bootstrap على إضافة التنسيقات على التطبيق ليبدو أكثر جاذبية بصريًا، كما سيساعدنا على تمكين ميزة الصفحات المتوافقة مع المتصفحات في تطبيق الويب، ما يضمن عمله بصورةٍ جيدة في المتصفحات الخاصة بالجوال، دون كتابة شيفرات HTML و CSS وجافا سكربت JavaScript لتحقيق هذه الغاية. وحتّى نستخدم بوتستراب سنضيفه إلى القالب الأساسي بحيث يسهل استخدامه في جميع القوالب الأُخرى. لذا سنفتح القالب الأساسي "base.html" للتعديل عليه: (env) user@localhost:$ nano templates/base.html ونعدله كما يلي: <!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous"> <title>{% block title %} {% endblock %} - FlaskApp</title> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container-fluid"> <a class="navbar-brand" href="{{ url_for('hello') }}">FlaskApp</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="{{ url_for('comments') }}">Comments</a> </li> <li class="nav-item"> <a class="nav-link" href="{{ url_for('about') }}">About</a> </li> </ul> </div> </div> </nav> <div class="container"> {% block content %} {% endblock %} </div> <!-- Optional JavaScript --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj" crossorigin="anonymous"></script> </body> </html> الجزء الأكبر من الشيفرة السابقة هو تعليمات لازمة لعمل بوتستراب، إذ تزوّد الوسوم <meta> متصفح الويب بالمعلومات، في حين ينشئ الوسم <link> ضمن القسم <head> ارتباطًا إلى ملفات CSS الخاصة ببوتستراب، وفي الجزء الأخير منه يُضمِّن الوسم <script> ارتباطًا إلى شيفرة جافا سكربت اختيارية. كما تتضمّن الشيفرة أجزاءً خاصةً بمحرك القوالب جينجا والتي قد وضّحناها فيما سبق، وكذلك استخدامًا لوسوم مُحدّدة وأصناف من CSS لتحديد كيفيّة عرض كل عنصر في بوتستراب. وقد استخدمنا في الشيفرة أعلاه وسم رابط <a> من الصنف navbar-brand الخاص بإضافة رابط العلامة المميزة (شعار الشركة مثلًا) إلى شريط التصفّح وذلك ضمن الوسم <nav> (الخاص بشريط التصفّح)، وفيه نحدّد رابط العلامة المطلوب، أمّا عن الروابط الاعتيادية مثل الروابط المؤدية إلى صفحات أُخرى من التطبيق، فمن الممكن تضمينها في الوسم <"ul class="navbar-nav> الحاوي على عنصر قائمة <li> ضمن عنصر روابط <a> وبالتالي من الممكن إضافة عدّة روابط. نحفظ الملف ونغلقه. وبعد التأكد من كون خادم التطوير ما يزال قيد التشغيل، ننتقل إلى الصفحة الرئيسية من التطبيق في المتصفح: http://127.0.0.1:5000/ فتظهر صفحةٌ مشابهةٌ لما يلي: وبذلك أصبح من الممكن استخدام مكونات بوتستراب لتنسيق مظهر العناصر في تطبيق فلاسك في جميع القوالب. الخاتمة تعرّفنا في هذا المقال على كيفيّة استخدام قوالب HTML في تطبيق فلاسك، إذ استخدمنا المتغيرات لتمرير البيانات من الخادم إلى القوالب مستفيدين من مفهوم وراثة القوالب لتجنُّب تكرار الشيفرات، كما استخدمنا عناصر مثل عبارات "if" الشرطية وحلقات "for" التكرارية، وربطنا بين صفحات مختلفة من صفحات التطبيق، كما تعرّفنا على كيفية تطبيق المُرشّحات لتعديل نص ما أو لعرض شيفرة HTML موثوقة، ونهايةً استخدمنا بوتستراب لتنسيق مظهر التطبيق. ترجمة -وبتصرف- للمقال How To Use Templates in a Flask Application لصاحبه Abdelhadi Dyouri. اقرأ أيضًا المقال التالي: كيفية التعامل مع الأخطاء في تطبيقات فلاسك Flask المقال السابق: تعلم بناء موقعك الإلكتروني الأول باستخدام إطار عمل فلاسك Flask بلغة بايثون استخدام أطر العمل في برمجة تطبيقات الويب: فلاسك نموذجا
    1 نقطة
  30. يُعد فلاسك إطار عمل للويب مبني بلغة بايثون، ويتميز بكونه صغير الحجم وسهل المعالجة، ويوفّر أيضًا عدة أدوات وميزات من شأنها جعل إنشاء تطبيقات الويب في لغة بايثون أسهل، مانحًا المطورين مرونةً في العمل، كما أنّه أبسط للاستخدام من قِبل المطورين المبتدئين نظرًا لإمكانية إنشاء تطبيق ويب كامل بسرعة باستخدام ملفٍ وحيدٍ مكتوب بلغة بايثون. إضافةً لما سبق، يتميز فلاسك بكونه قابلًا للتوسّع والوراثة دون أن يفرض أي بنية هرمية لطريقة عرض الملفات، كما أنّه لا يتطلب أي شيفرات برمجية معقدّة استهلالية قبل البدء باستخدامه. سيمكِّننا تعلُّم فلاسك من إنشاء تطبيقات ويب بسهولة وسرعة باستخدام لغة بايثون، إذ سنستخدم مكتبات بايثون لإضفاء ميزات إضافية على تطبيق الويب، مثل تخزين البيانات في قواعد البيانات والتحقق من بيانات نماذج الإدخال في الويب. سنبني في هذا المقال تطبيق ويب صغير يعمل على تصيّير النصوص المكتوبة بلغة HTML ضمن المتصفح، إذ سنثبّت فلاسك، ثمّ سنكتب الشيفرة البرمجية الخاصّة بتطبيق فلاسك ونشغّله في وضع التطوير، وسنستخدم مفهوم التوجيه للتنقّل بين عدة صفحات ويب تؤدي وظائف مختلفة ضمن التطبيق؛ كما سنسمح للمستخدمين من خلال دوال فلاسك بالتفاعل مع التطبيق عبر وجهات routes ديناميكية، ونهايةً سنعمل على حل المشكلات الناتجة عن أي أخطاء باستخدام مُنقّح الأخطاء. مستلزمات العمل قبل المتابعة في هذا المقال لا بُدّ من: توفُّر بيئة برمجة بايثون 3 محلية، مثبّتة على حاسوبك، وسنفترض في مقالنا أن اسم مجلد المشروع هو "flask_app". فهم مبادئ بايثون 3، مثل أنماط البيانات والقوائم والدوال، وغيرها من المفاهيم المشابهة في بايثون 3. فهم أساسيات لغة HTML. الخطوة الأولى – تثبيت فلاسك سنفعّل في هذه الخطوة بيئة بايثون ونثبّت فلاسك باستخدام مثبِّت الحزم "pip". بدايةً، سنفعّل بيئة البرمجة في حال كانت غير مفعّلةٍ بعد كما يلي: $ source env/bin/activate بعدها نثبّت فلاسك باستخدام الأمر pip install: (env)user@localhost:$ pip install flask وحالما ينتهي التثبيت، سيظهر الخرج مُتضمنًا مجموعة الحزم المُثبّتة كما يلي: ... Installing collected packages: Werkzeug, MarkupSafe, Jinja2, itsdangerous, click, flask Successfully installed Jinja2-3.0.1 MarkupSafe-2.0.1 Werkzeug-2.0.1 click-8.0.1 flask-2.0.1 itsdangerous-2.0.1 ومنه نلاحظ أنّه أثناء تثبيت فلاسك تُثبّت أيضًا عدة حزم ومستلزمات خاصة يستخدمها فلاسك في تنفيذ العديد من الدوال المختلفة. ومع نهاية هذه الخطوة نكون قد أنشأنا مجلد للتطبيق وفعّلنا البيئة الافتراضية وثبّتنا فلاسك، وبذلك نكون مستعدين للانتقال إلى الخطوة التالية المُتمثّلة بإنشاء تطبيق بسيط. الخطوة الثانية – إنشاء تطبيق بسيط يمكننا الآن البدء باستخدام فلاسك بعدما أصبحت البيئة البرمجية جاهزة، إذ سننشئ في هذه الخطوة تطبيق ويب مُصغّر باستخدام فلاسك وذلك ضمن ملف بايثون، الذي سنكتب فيه أيضًا شيفرات HTML لإظهارها عند التشغيل ضمن المتصفح. الآن، سنفتح الملف المسمى "app.py" الموجود ضمن المجلد "flask_app" بهدف التعديل عليه وذلك باستخدام محرر النصوص نانو nano، أو أي محرّر آخر تفضّله: (env)user@localhost:$ nano app.py ونكتب الشيفرة التالية ضمن الملف app.py: from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return '<h1>Hello, World!</h1>' نحفظ الملف ونغلقه. استوردنا في الجزء السابق من الشيفرة كائن فلاسك من حزمة فلاسك، ثم استخدمناه لإنشاء نسخةٍ instance فعليةٍ موجودةٍ في الذاكرة لتطبيق فلاسك Flask application instance باسم app، وليست مجرد كائن برمجي، ثمّ مررنا المتغير الخاص __name__، الذي سيخزّن اسم وحدة بايثون الحالية ليُعلم تطبيق فلاسك بمكان وجود هذه الوحدة، إذ لا بُدّ من إجراء هذه الخطوة كون فلاسك يهيّئ بعض المسارات اللازمة في الخلفية. وبمجرد إنشاء هذا التطبيق "app"، يمكنك استخدامه في معالجة طلبات الويب القادمة وإرسال الردود إلى المُستخدم. يكون المزخرف app.route@ مسؤولًا عن تعديل دوال بايثون المألوفة لتصبح دوال عرض view في فلاسك، والتي تحوّل القيمة المُعادة من قِبل الدالة إلى استجابةٍ من نوع HTTP تُعرض لدى عميل HTTP، الذي قد يكون متصفحًا مثلًا؛ فبمجرد تمرير "/" للدالة ()app.route@، سينشئ الردود على طلبات الويب الواردة إلى الرابط "/"، والذي يمثّل الرابط الرئيسي في التطبيق، وبذلك ستعيد الدالة ()hello السلسلة النصية "!Hello, World" ردًا على الطلب. وبذلك أصبح لدينا تطبيق فلاسك بسيط موجود ضمن ملف بايثون المُسمّى "app.py"، سنشغّل فيما يلي هذا التطبيق لتصيير نتيجة دالة العرض ()hello ضمن متصفح ويب. الخطوة الثالثة – تشغيل التطبيق بعد إنشائنا الملف الذي يحتوي على تطبيق فلاسك، سنشغّله باستخدام واجهة أوامر فلاسك وذلك لتشغيل خادم التطوير وتصيير شيفرة HTML ضمن المتصفح والتي كتبناها لتكون القيمة المعادة من الدالة ()hello في الخطوة السابقة. ولتشغيل تطبيق الويب الذي أنشأناه، وبعد التأكّد من وجودنا ضمن المجلد "flask_app" مع تفعيل البيئة الافتراضية، لا بُدّ من إرشاد فلاسك إلى موقع التطبيق (في حالتنا الملف ذو الاسم "app.py") وذلك باستخدام متغير بيئة فلاسك FLASK_APP على النحو التالي (مع ملاحظة أنّنا نستخدم الأمر set في بيئة ويندوز عوضًا عن الأمر export): (env)user@localhost:$ export FLASK_APP=app ثم نحدد وضع تشغيل التطبيق ليكون بوضع التطوير، وذلك باستخدام متغير بيئة فلاسك Flask_ENV على النحو التالي: (env)user@localhost:$ export FLASK_ENV=development وبذلك نتمكّن من استخدام المنقّح لالتقاط الأخطاء. نهايةً، نشغّل التطبيق باستخدام الأمر flask run: (env)user@localhost:$ flask run حالما يعمل التطبيق، يظهر الخرج على النحو التالي: * Serving Flask app "app" (lazy loading) * Environment: development * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 296-353-699 يحتوي الخرج السابق على عدة معلومات، مثل: اسم التطبيق المُشغَّل. بيئة التشغيل الحالية التي يعمل عليها التطبيق. عبارة Debug mode:on التي تشير إلى أن مُنقّح أخطاء فلاسك قيد التشغيل، وهو ذو فوائد عديدة أثناء عملية التطوير كونه يقدم رسائل خطأ مفصّلة عندما يحدث أي خلل، وهذا ما يجعل عملية تنقيح الأخطاء أسهل وأيسر. التطبيق يعمل على الحاسب المحلي وذلك على الرابط /http://127.0.0.1:5000، إذ أن "127.0.0.1" هو عنوان IP الذي يمثِّل الخادم المحلي localhost على حاسبك، و "5000:" هو رقم المنفذ. افتح المتصفح واكتب عنوان URL التالي "/http://127.0.0.1:5000"، ستظهر عبارة "!Hello, World" (ضمن تنسيق عنوان من المستوى الأوّل <h1>) استجابةً لهذا العنوان، وهذا ما يؤكد أن التطبيق يعمل بنجاح. وإذا أردنا إيقاف خادم التطوير، نضغط على "CTRL+C". تنبيه: يستخدم فلاسك خادم ويب مبسّط لاستضافة تطبيق الويب في بيئة التطوير، ما يعني أن مُنقّح أخطاء فلاسك قيد التشغيل أيضًا كي يجعل التقاط الأخطاء أسهل، ولا ينبغي استخدام خادم التطوير هذا عندما يُنقل التطبيق إلى مرحلة التشغيل الفعلي أي نشر المنتج. يمكن في هذه المرحلة الإبقاء على خادم التطوير قيد التشغيل في الطرفية terminal الخاصة به، ومن ثم فتح نافذة طرفية جديدة وتغيير المسار فيها إلى مسار مجلد المشروع حيث يتواجد ملف "hello.py"، ثم بعد ذلك تفعيل البيئة الافتراضية (السبب مبيّنٌ في الملاحظة أدناه)، وتهيّئة متغيرات البيئة FLASK_ENV و FLASK_APP، ومتابعة الخطوات التالية. (ذُكرت هذه الأوامر سابقًا في هذه الخطوة). ملاحظة: من الضروري تفعيل البيئة الافتراضية لدى فتح طرفية جديدة، أو إغلاق الطرفية الحالية التي تشغّل خادم التطوير عليها وتود إعادة تشغيله، ولا بدّ من إعداد متغيرات البيئة FLASK_ENV و FLASK_APP ليعمل الأمر flask run بصورةٍ صحيحة. كل ما عليك فعله هو تشغيل الخادم مرةً واحدةً في نافذة طرفية واحدة. لا يمكن تشغيل تطبيق فلاسك آخر باستخدام الأمر flask run نفسه خلال فترة عمل خادم تطوير تطبيقات فلاسك، كونه يستخدم المنفذ رقم 5000 افتراضيًا، وحالما يُحجَز هذا المنفذ يصبح غير متاحًا لتشغيل أي تطبيقٍ آخر، وفي حال فعلت ذلك ستظهر رسالة خطأ مشابهةٍ لما يلي: OSError: [Errno 98] Address already in use ويمكن حل لهذه المشكلة، إمّا بإيقاف الخادم العامل حاليًا عن طريق الضغط على "CTRL+C" ومن ثم تنفيذ الأمر flask run مجدّدًا، أو في حال رغبتك بتشغيل كلا التطبيقين في نفس الوقت، فمن الممكن تمرير رقم منفذٍ مختلف باستخدام الوسيط p-. سنستخدم الأمر التالي لتشغيل تطبيقٍ آخر يستخدم المنفذ "5001" مثالًا حول طريقة الحل هذه: (env)user@localhost:$ flask run -p 5001 وبذلك يصبح لدينا تطبيق أوّل يعمل على الرايط "/http://172.0.0.1:5000" وآخر يعمل على الرابط "/http://172.0.0.1:5001" إن احتجنا لذلك. وبذلك يكون قد أصبح لدينا مع نهاية هذه الخطوة تطبيق ويب صغير باستخدام فلاسك، وبعد أن شغّلنا وعرضنا المعلومات في متصفح الويب، سنتعلم فيما يلي كيفية إنشاء وجهات واستخدامها لتخديم عدّة صفحات ويب. الخطوة الرابعة – الوجهات ودوال العرض في فلاسك سنضيف في هذه الخطوة بضع وجهات للتطبيق لإظهار صفحات مختلفة اعتمادًا على الرابط المطلوب، وسنتعرف أيضًا على دوال العرض في فلاسك وكيفية استخدامها. تُعرّف الوجهة route بأنها رابطٌ يُستخدم لتحديد ما سيستقبله المستخدم لدى زيارة تطبيق الويب على متصفحه، فمثلًا يشير الرابط "/http://127.0.0.1:5000" إلى الوجهة الرئيسية التي يمكن استخدامها لعرض الصفحة الرئيسية للتطبيق، بينما يشير الرابط "http://127.0.0.1:5000/about" إلى وجهةٍ أخرى وهو صفحة المعلومات التي تعطي الزوار معلومات حول تطبيق الويب، وعلى نحوٍ مشابه يمكن إنشاء وجهة تسمح للمستخدمين بتسجيل الدخول إلى تطبيق الويب عبر الرابط "http://127.0.0.1:5000/login" مثلًا. يستخدم تطبيق فلاسك الذي أنشأناه حاليًا وجهةً واحدةً تخدّم الزوار الذين يطلبون الرابط الرئيسي "/http://127.0.0.1:5000". الآن، ولنبين كيفية إضافة صفحة ويب جديدة إلى تطبيقنا، سنعدّل ملف التطبيق لإضافة وجهةٍ جديدة تؤمن معلومات حول التطبيق عبر الرابط "http://127.0.0.1:5000/about". لذا سنفتح الملف "app.py" من أجل التعديل: (env)user@localhost:$ nano app.py ثمّ نعدّل الملف من خلال إضافة الشيفرة التالية: from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return '<h1>Hello, World!</h1>' @app.route('/about/') def about(): return '<h3>This is a Flask web application.</h3>' نحفظ الملف ونغلقه. أضفنا في الشيفرة السابقة دالةً جديدةً باسم ()about، والتي صمّمناها باستخدام المًزخرف ()app.route@، الذي يحوّلها إلى دالة عرض قادرة على التعامل مع الطلبات الواردة إلى الرابط "http://127.0.0.1:5000/about". بعد التأكد من كون خادم التطوير ما يزال قيد التشغيل، نزور الرابط التالي في المتصفح: http://127.0.0.1:5000/about فيظهر النص "This is a Flask web application" مصّيرًا ضمن تنسيق عنوان من المستوى الثالث <h3> في HTML؛ كما من الممكن استخدام عدّة وجهات في دالة فلاسك الواحدة، فمثلًا من الممكن تخديم الصفحة الرئيسية للتطبيق بكل من الوجهتين "/" و "/index/"، ولتنفيذ ذلك سنفتح الملف "app.py" لتعديله: (env)user@localhost:$ nano app.py سنعدّل الملف بإضافة مُزخرف آخر إلى دالة فلاسك ()hello: from flask import Flask app = Flask(__name__) @app.route('/') @app.route('/index/') def hello(): return '<h1>Hello, World!</h1>' @app.route('/about/') def about(): return '<h3>This is a Flask web application.</h3>' نحفظ الملف ونغلقه. وبعد إضافة المُزخرف الثاني أصبح بالإمكان الوصول إلى الصفحة الرئيسية للتطبيق من خلال أي من الرابطين "/http://127.0.0.1:5000" أو "http://127.0.0.1:5000/index". تعرّفنا فيما سبق على الوجهات وكيفية استخدامها لإنشاء دوال عرض في فلاسك وكيفية إضافة وجهات جديدة إلى التطبيق. فيما يلي سنستخدم الوجهات الديناميكية المرنة للسماح للمستخدمين بالتحكم باستجابة التطبيق. الخطوة الخامسة - الوجهات الديناميكية سنستخدم في هذه الخطوة الوجهات الديناميكية لنمكّن المستخدمين من التفاعل مع التطبيق، إذ سننشئ وجهةً تجعل الكلمات المُمرّرة عبر الرابط مكتوبةً بأحرف كبيرة، كما سننشئ وجهةً تجمع رقمين مع بعضهما وتظهر النتيجة. لا يتفاعل المستخدمون عادةً مع تطبيق الويب من خلال التعديل اليدوي للرابط، بل يتفاعلون مع عناصر موجودة في الصفحة تؤدي إلى روابط مختلفة بناءً على مدخلاتهم وتصرفاتهم ضمن الصفحة، ولكن وبهدف التبسيط في هذا المقال، سنعدّل الرابط لنبيّن كيفية جعل التطبيق يستجيب بصورةٍ مختلفة بروابط مختلفة. سنفتح بدايةً الملف app.py لتعديله: (env)user@localhost:$ nano app.py مع ملاحظة انّه إذا سمحنا للمستخدم بإدخال شيءٍ ما إلى التطبيق، مثل إدخال قيمة في الرابط كما سنفعل في التعديل التالي، فيجب الانتباه إلى أنّ التطبيق يجب ألا يُظهر بيانات غير موثوقة (البيانات التي أدخلها المستخدم)، ولكي نعرض بيانات المستخدم بصورةٍ آمنة، سنستخدم الدالة "()escape" الموجودة ضمن حزمة البناء الآمن "markupsafe" المُثبتة بالتوازي مع تثبيت فلاسك. الأن، سنعدّل الملف "app.py" بإضافة السطر التالي في بدايته أعلى أمر استيراد Flask كما يلي: from markupsafe import escape from flask import Flask # ... ثمّ سنضيف الوجهة التالية إلى نهاية الملف: # ... @app.route('/capitalize/<word>/') def capitalize(word): return '<h1>{}</h1>'.format(escape(word.capitalize())) نحفظ الملف ونغلقه. تملك الوجهة الجديدة قسمًا متغيرًا مُضمّنًا في الوسم <word>، والذي يسمح لفلاسك بأخذ القيمة المُدخلة من الرابط وتمريرها إلى دالة فلاسك، إذ يُمرّر متغير الرابط <word> الكلمة مثل وسيط إلى دالة فلاسك ()capitalize. وفي حالتنا فإنّ الوسيط هذا يملك نفس اسم متغير الرابط (وهو word في حالتنا)، وبذلك يمكننا الوصول إلى الكلمة المُمررة عبر الرابط وإنشاء استجابة بنفس الكلمة المُمررة ولكن بأحرف كبيرة وذلك باستخدام دالة العرض ()capitalize العاملة أصلًا في بايثون. استخدمنا الدالة ()escape التي استوردناها سابقًا لتصيير السلسلة التي أدخلها المُستخدم والموجودة ضمن المتغير word مثل نص وليس شيفرةً للتنفيذ، وهو أمر بالغ الأهمية لتجنب هجمات البرمجة العابرة للمواقع XSS، ففي حال إدخال المستخدم شيفرة JavaScript خبيثة بدلًا من السلسلة النصية، تصيّرها الدالة ()escape على أنها نص عادي وبذلك لن ينفّذها المتصفح، ما يبقي تطبيق الويب آمنًا. ولعرض الكلمات بأحرف كبيرة ضمن تنسيق عنوان من المستوى الأوّل <h1> في HTML استخدمنا الدالة ()format من دوال بايثون. الآن وبعد التأكد من أنّ خادم التطوير ما يزال قيد التشغيل، نفتح المتصفح ونذهب إلى الروابط التالية، مع إمكانية تبديل الكلمات "hello" و "flask" و "python" التي تنتهي الروابط بها في مثالنا بأي كلمة تريد: http://127.0.0.1:5000/capitalize/hello http://127.0.0.1:5000/capitalize/flask http://127.0.0.1:5000/capitalize/python وبذلك تظهر الكلمة ضمن المتصفح بأحرف كبيرة وبتنسيق عنوان من المستوى الأول <h1>. كما يمكننا استخدام عدّة متغيرات في الوجهة، ولتوضيح ذلك سنضيف وجهةً جديدةً لجمع رقمين صحيحين ويعرض النتيجة. لذا سنفتح الملف "app.py" لتعديله: (env)user@localhost:$ nano app.py ثمّ نضيف الوجهة التالية إلى نهاية الملف: # ... @app.route('/add/<int:n1>/<int:n2>/') def add(n1, n2): return '<h1>{}</h1>'.format(n1 + n2) نحفظ الملف ونغلقه. نستخدم في هذه الوجهة المحوّل الخاص int مع المتغير الخاص بالرابط (/add/<int:n1>/<int:n2>‎/)؛ ومهمّة هذا المحوّل هي قبول القيم التي تُمثّل أعدادًا صحيحة موجبة فقط والتعامل معها على أنها أعداد، كونه افتراضيًا تُعدّ المتغيرات الآتية من الرابط سلاسلًا محرفية ويجري التعامل معها على هذا الأساس، وهذا أمرٌ غير مناسب لإتمام عملية الجمع العددي. الآن وبعد التأكد من أنّ خادم التطوير ما يزال قيد التشغيل، نفتح المتصفح ونذهب إلى الرابط التالي: http://127.0.0.1:5000/add/5/5/ وستكون النتيجة مجموع الرقمين (وهي "10" في حالة مثالنا هذا). تعرفنا في هذه الخطوة على كيفية استخدام الوجهات الديناميكية لعرض استجابات مُختلفة ضمن الوجهة الواحدة اعتمادًا على الرابط المطلوب، وهذا ما يعزز التجربة التفاعلية للمُستخدم. سنتعرّف في الخطوة التالية على آليات تنقيح وتصحيح الأخطاء في تطبيق فلاسك في حال حدوثها. الخطوة السادسة - تنقيح أخطاء تطبيق فلاسك خلال مراحل تطوير أي تطبيق ويب، من الطبيعي أن نمر بحالات نحصل فيها على أخطاء لدى تشغيل التطبيق عوضًا عن النتيجة المتوقعة، والتي قد تكون ناتجةً مثلًا عن خطأ إملائي بسيط في كتابة اسم أحد المتغيرات أو نتيجة نسيان التصريح عن أو استيراد إحدى الدوال؛ ولإصلاح هذه الأخطاء بسهولة يوفّر فلاسك منقّح أخطاء يعمل لدى تشغيل التطبيق في وضع التطوير، إذ سنتعلّم في هذه الخطوة آلية تصحيح أخطاء التطبيق بالاعتماد على مُنقّح الأخطاء في فلاسك. لتوضيح كيفية التعامل مع الأخطاء في حال ظهورها، سننشئ وجهةً للترحيب بمستخدم ما من قائمة أسماء مستخدمين موجودة. لذا سنفتح الملف "app.py" للتعديل عليه: (env)user@localhost:$ nano app.py ونضيف الوجهة التالية إلى نهاية الملف: # ... @app.route('/users/<int:user_id>/') def greet_user(user_id): users = ['Ahmad', 'Mohammad', 'Adam'] return '<h2>Hi {}</h2>'.format(users[user_id]) نحفظ الملف ونغلقه. تستقبل دالة فلاسك ()greet_user في الوجهة السابقة متغير الرابط user_id مثل قيمة للوسيط user_id، إذ استخدمنا المحوّل الخاص int لقبول أعداد صحيحة موجبة فقط، حيث تتضمّن الدالة قائمةً مبنيةً في بايثون باسم users تحتوي على ثلاث سلاسل نصية تمثّل أسماء المستخدمين، وترجع دالة فلاسك السلسة الموافقة من القائمة اعتمادًا على قيمة المتغير user_id المُمرّر والذي يدل على رقم المُستخدم المراد الترحيب به بالنتيجة؛ فإذا كانت قيمة المتغير user_id تساوي "0" مثلًا، ستكون الاستجابة ظهور عبارة "Hi Ahmad" ضمن تنسيق عنوان من المستوى الثاني <h2> لأن Ahmad هو أول عنصر في القائمة المُقابل للقيمة "[user[0". الآن وبعد التأكد أن خادم التطوير ما يزال قيد التشغيل، سنفتح المتصفح لزيارة الروابط التالية: http://127.0.0.1:5000/users/0 http://127.0.0.1:5000/users/1 http://127.0.0.1:5000/users/2 فتكون النتيجة على النحو التالي: Hi Ahmad Hi Mohammad Hi Adam نلاحظ أنّ الأمور تجري على خير ما يرام حتى الآن، ولكن ماذا لو طلبنا الترحيب بمستخدم غير موجود؟ سيظهر خطأ بالتأكيد، ولتوضيح كيفية عمل مُنقّح الأخطاء في فلاسك سنزور الرابط التالي: http://127.0.0.1:5000/users/3 فتظهر صفحةٌ كما في الصورة أدناه: نلاحظ أنّ اسم الخطأ الحاصل في بايثون وهو IndexError في حالتنا يُعرض في أعلى الصفحة، ويشير هذا الخطأ إلى وقوع دليل القائمة ("3" في مثالنا) خارج المجال، إذ أن المجال في حالتنا محصورٌ بين "0" و "2" لأنّ القائمة مكونةٌ من ثلاثة عناصر، كما يظهر في مُنقح الأخطاء جميع أسطر الشيفرة التي أدّى تنفيذها إلى ظهور هذا الخطأ. وعادةً ما يتضمّن آخر سطرين من متتبّع الأخطاء مصدر الخطأ، وفي حالتنا سيبدوان على نحو مشابه لما يلي: File "/home/USER/flask_app/app.py", line 28, in greet_user return '<h2>Hi {}</h2>'.format(users[user_id]) ما يشير إلى أنّ الخطأ ناتج عن دالة الترحيب ()greet_user ضمن الملف "app.py" وتحديدًا في السطر الحاوي غلى القيمة المُعادة return، ومع معرفتنا للسطر الذي تسبّب بالخطأ يصبح تحديد المشكلة وحلها أسهل. كما يمكننا لتجنّب توقّف عمل التطبيق في حالات مشابهة لهذه الحالة استخدام العبارة "try…except" لإصلاح الخطأ، بحيث إذا احتوى الرابط المطلوب على دليل خارج مجال القائمة يتلقى المستخدم عبارة خطأ "404 Not Found"، وهو خطأ HTTP يشير للمستخدم أن الصفحة التي يطلبها غير متوفرة. لذا سنفتح الملف "app.py" للتعديل عليه: (env)user@localhost:$ nano app.py وحتى تحدث الاستجابة بخطأ من النوع HTTP 404 سنستخدم دالة فلاسك ()abort التي يمكن استخدامها لانشاء استجابات مكونة من أخطاء HTTP، لذا سنغير السطر الثاني في الملف ليصبح كما يلي: from markupsafe import escape from flask import Flask, abort ثمّ سنعدّل الدالة ()greet_user لتصبح كما يلي: # ... @app.route('/users/<int:user_id>/') def greet_user(user_id): users = ['Ahmad', 'Mohammad', 'Adam'] try: return '<h2>Hi {}</h2>'.format(users[user_id]) except IndexError: abort(404) استخدمنا try لاختبار التعبير return والتأكّد من خلوه من الأخطاء، فإذا لم يكن هناك خطأ، بمعنى أنّ قيمة المتغير user_id المُمرّرة صحيحةٌ ومن ضمن مجال قائمة users، فسيستجيب التطبيق بالترحيب المناسب، وإلّا وفي حال كون قيمة user_id خارج مجال القائمة، سيُفعَّل الاستثناء IndexError، ونستخدم الأمر except للتعامل مع الخطأ وبالتالي الاستجابة بخطأ من نوع HTTP 404 باستخدام دالة فلاسك المساعدة ()abort. الآن وبعد التأكد من كون خادم التطوير قيد التشغيل، نزور الرابط مجددًا مع تمرير القيمة 3 لرقم المُستخدم المطلوب: http://127.0.0.1:5000/users/3 فتظهر في هذه الحالة صفحة الخطأ 404 التقليدية لتشير للمستخدم أن الصفحة المطلوبة غير موجودة. ومع نهاية تطبيق الخطوات الواردة في هذا المقال، سيبدو الملف "app.py" على النحو التالي: from markupsafe import escape from flask import Flask, abort app = Flask(__name__) @app.route('/') @app.route('/index/') def hello(): return '<h1>Hello, World!</h1>' @app.route('/about/') def about(): return '<h3>This is a Flask web application.</h3>' @app.route('/capitalize/<word>/') def capitalize(word): return '<h1>{}</h1>'.format(escape(word.capitalize())) @app.route('/add/<int:n1>/<int:n2>/') def add(n1, n2): return '<h1>{}</h1>'.format(n1 + n2) @app.route('/users/<int:user_id>/') def greet_user(user_id): users = ['Ahmad', 'Mohammad', 'Adam'] try: return '<h2>Hi {}</h2>'.format(users[user_id]) except IndexError: abort(404) وبذلك أصبح لديك تصوّر عام عن كيفية استخدام مُنقّح الأخطاء في فلاسك لالتقاط الأخطاء وتحديد الآلية المُثلى لإصلاحها والتعامل معها. الخاتمة تعرفنا في هذا المقال بصورة عامة على فلاسك وكيفية تثبيته واستخدامه لإنشاء تطبيق ويب، كما تعرفنا على آلية تشغيل خادم التطوير واستخدام الوجهات ودوال فلاسك لعرض صفحات ويب مختلفة تخدّم وظائفًا محددة، كما تعلمنا كيفية استخدام الوجهات الديناميكية للسماح للمستخدم بالتفاعل مع تطبيق ويب عن طريق تعديل الرابط المطلوب، وفي النهاية تعلمنا كيفية استخدام مُنقّح الأخطاء لتحديد المشاكل. ترجمة -وبتصرف- للمقال How To Create Your First Web Application Using Flask and Python3 لصاحبه Abdelhadi Dyouri. اقرأ أيضًا المقال التالي: كيفية استخدام القوالب في تطبيقات فلاسك Flask المقال السابق: تخديم تطبيقات فلاسك باستخدام خادمي الويب uWSGI و Nginx إنشاء تطبيق ويب باستخدام إطار عمل فلاسك Flask من لغة بايثون بناء موقعك واستضافته باستخدام Git أساسيات تحديد التكلفة المادية الكاملة لبناء موقع ويب
    1 نقطة
  31. ما هي اللغة التي تحاولين الحل من خلالها؟
    0 نقاط
×
×
  • أضف...