العربية

استكشاف متعمق لـ Tornado، وهو إطار عمل ويب ومكتبة شبكات غير متزامنة في بايثون. تعلم كيفية بناء تطبيقات قابلة للتطوير وعالية الأداء مع شروحات مفصلة وأمثلة وأفضل الممارسات.

وثائق Tornado: دليل شامل للمطورين حول العالم

Tornado هو إطار عمل ويب ومكتبة شبكات غير متزامنة في بايثون، تم تطويره في الأصل في FriendFeed. وهو مناسب بشكل خاص للاستقصاء الطويل (long-polling)، و WebSockets، والتطبيقات الأخرى التي تتطلب اتصالاً طويل الأمد بكل مستخدم. إن إدخال/إخراج الشبكة غير الحاجب (non-blocking) يجعله قابلاً للتطوير بدرجة كبيرة وخيارًا قويًا لبناء تطبيقات ويب عالية الأداء. سيرشدك هذا الدليل الشامل عبر المفاهيم الأساسية لـ Tornado ويقدم أمثلة عملية لتبدأ.

ما هو Tornado؟

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

الميزات الرئيسية لـ Tornado:

إعداد بيئة Tornado الخاصة بك

قبل الغوص في تطوير Tornado، ستحتاج إلى إعداد بيئتك. إليك دليل خطوة بخطوة:

  1. تثبيت بايثون: تأكد من أن لديك بايثون 3.6 أو أعلى مثبتًا. يمكنك تنزيله من موقع بايثون الرسمي (python.org).
  2. إنشاء بيئة افتراضية (موصى به): استخدم venv أو virtualenv لإنشاء بيئة معزولة لمشروعك:
    python3 -m venv myenv
    source myenv/bin/activate  # على Linux/macOS
    myenv\Scripts\activate  # على Windows
  3. تثبيت Tornado: قم بتثبيت Tornado باستخدام pip:
    pip install tornado

تطبيقك الأول مع Tornado

لنقم بإنشاء تطبيق "أهلاً بالعالم!" بسيط باستخدام Tornado. أنشئ ملفًا باسم app.py وأضف الكود التالي:

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
 def get(self):
  self.write("Hello, World!")

def make_app():
 return tornado.web.Application([
  (r"/", MainHandler),
 ])

if __name__ == "__main__":
 app = make_app()
 app.listen(8888)
 tornado.ioloop.IOLoop.current().start()

الآن، قم بتشغيل التطبيق من الطرفية الخاصة بك:

python app.py

افتح متصفح الويب الخاص بك وانتقل إلى http://localhost:8888. يجب أن ترى رسالة "Hello, World!".

الشرح:

معالجات الطلبات والتوجيه

معالجات الطلبات هي أساس تطبيقات ويب Tornado. هي تحدد كيفية التعامل مع طلبات HTTP الواردة بناءً على عنوان URL. يقوم التوجيه بربط عناوين URL بمعالجات طلبات محددة.

تحديد معالجات الطلبات:

لإنشاء معالج طلبات، قم بإنشاء فئة فرعية من tornado.web.RequestHandler وقم بتنفيذ توابع HTTP المناسبة (get، post، put، delete، إلخ).

class MyHandler(tornado.web.RequestHandler):
 def get(self):
  self.write("This is a GET request.")

 def post(self):
  data = self.request.body.decode('utf-8')
  self.write(f"Received POST data: {data}")

التوجيه:

يتم تكوين التوجيه عند إنشاء tornado.web.Application. أنت تقدم قائمة من الصفوف (tuples)، حيث يحتوي كل صف على نمط URL ومعالج الطلب المقابل.

app = tornado.web.Application([
 (r"/", MainHandler),
 (r"/myhandler", MyHandler),
])

أنماط URL:

أنماط URL هي تعبيرات نمطية. يمكنك استخدام مجموعات التعبيرات النمطية لالتقاط أجزاء من عنوان URL وتمريرها كوسائط إلى توابع معالج الطلب.

class UserHandler(tornado.web.RequestHandler):
 def get(self, user_id):
  self.write(f"User ID: {user_id}")

app = tornado.web.Application([
 (r"/user/([0-9]+)", UserHandler),
])

في هذا المثال، /user/([0-9]+) يطابق عناوين URL مثل /user/123. الجزء ([0-9]+) يلتقط رقمًا واحدًا أو أكثر ويمررها كوسيط user_id إلى تابع get الخاص بـ UserHandler.

القوالب

يتضمن Tornado محرك قوالب بسيط وفعال. تُستخدم القوالب لإنشاء HTML ديناميكيًا، وفصل منطق العرض عن منطق التطبيق.

إنشاء القوالب:

عادة ما يتم تخزين القوالب في ملفات منفصلة (على سبيل المثال، index.html). إليك مثال بسيط:

<!DOCTYPE html>
<html>
<head>
 <title>My Website</title>
</head>
<body>
 <h1>Welcome, {{ name }}!</h1>
 <p>Today is {{ today }}.</p>
</body>
</html>

{{ name }} و {{ today }} هي عناصر نائبة سيتم استبدالها بقيم فعلية عند عرض القالب.

عرض القوالب:

لعرض قالب، استخدم التابع render() في معالج الطلب الخاص بك:

class TemplateHandler(tornado.web.RequestHandler):
 def get(self):
  name = "John Doe"
  today = "2023-10-27"
  self.render("index.html", name=name, today=today)

تأكد من تكوين إعداد template_path بشكل صحيح في إعدادات تطبيقك. افتراضيًا، يبحث Tornado عن القوالب في دليل يسمى templates في نفس دليل ملف التطبيق الخاص بك.

app = tornado.web.Application([
 (r"/template", TemplateHandler),
], template_path="templates")

صيغة القوالب:

تدعم قوالب Tornado ميزات متنوعة، بما في ذلك:

العمليات غير المتزامنة

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

@tornado.gen.coroutine:

يسمح لك المُزخرف @tornado.gen.coroutine بكتابة كود غير متزامن باستخدام الكلمة المفتاحية yield. هذا يجعل الكود غير المتزامن يبدو ويتصرف بشكل أشبه بالكود المتزامن، مما يحسن من قابلية القراءة والصيانة.

import tornado.gen
import tornado.httpclient

class AsyncHandler(tornado.web.RequestHandler):
 @tornado.gen.coroutine
 def get(self):
  http_client = tornado.httpclient.AsyncHTTPClient()
  response = yield http_client.fetch("http://example.com")
  self.write(response.body.decode('utf-8'))

في هذا المثال، http_client.fetch() هي عملية غير متزامنة تُرجع كائن Future. تقوم الكلمة المفتاحية yield بتعليق تنفيذ الروتين المساعد (coroutine) حتى يتم حل الـ Future. بمجرد حل الـ Future، يستأنف الروتين المساعد ويتم كتابة جسم الاستجابة إلى العميل.

tornado.concurrent.Future:

يمثل كائن Future نتيجة عملية غير متزامنة قد لا تكون متاحة بعد. يمكنك استخدام كائنات Future لربط العمليات غير المتزامنة معًا والتعامل مع الأخطاء.

tornado.ioloop.IOLoop:

IOLoop هو قلب محرك Tornado غير المتزامن. يراقب واصفات الملفات والمقابس للأحداث ويرسلها إلى المعالجات المناسبة. عادةً ما لا تحتاج إلى التفاعل مع IOLoop مباشرةً، ولكن من المهم فهم دوره في التعامل مع العمليات غير المتزامنة.

WebSockets

يوفر Tornado دعمًا ممتازًا لـ WebSockets، مما يتيح الاتصال في الوقت الفعلي بين الخادم والعملاء. تعتبر WebSockets مثالية للتطبيقات التي تتطلب اتصالًا ثنائي الاتجاه ومنخفض الكمون، مثل تطبيقات الدردشة والألعاب عبر الإنترنت ولوحات المعلومات في الوقت الفعلي.

إنشاء معالج WebSocket:

لإنشاء معالج WebSocket، قم بإنشاء فئة فرعية من tornado.websocket.WebSocketHandler وقم بتنفيذ التوابع التالية:

import tornado.websocket

class WebSocketHandler(tornado.websocket.WebSocketHandler):
 def open(self):
  print("WebSocket opened")

 def on_message(self, message):
  self.write_message(f"You sent: {message}")

 def on_close(self):
  print("WebSocket closed")

 def check_origin(self, origin):
  return True # تمكين اتصالات WebSocket عبر المصادر

دمج WebSockets في تطبيقك:

أضف معالج WebSocket إلى تكوين التوجيه في تطبيقك:

app = tornado.web.Application([
 (r"/ws", WebSocketHandler),
])

التنفيذ من جانب العميل:

من جانب العميل، يمكنك استخدام JavaScript لإنشاء اتصال WebSocket وإرسال/استقبال الرسائل:

const websocket = new WebSocket("ws://localhost:8888/ws");

websocket.onopen = () => {
 console.log("WebSocket connection established");
 websocket.send("Hello from the client!");
};

websocket.onmessage = (event) => {
 console.log("Received message:", event.data);
};

websocket.onclose = () => {
 console.log("WebSocket connection closed");
};

المصادقة والأمان

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

المصادقة:

المصادقة هي عملية التحقق من هوية المستخدم. يوفر Tornado دعمًا مدمجًا لمختلف أنظمة المصادقة، بما في ذلك:

الترخيص:

الترخيص هو عملية تحديد ما إذا كان لدى المستخدم إذن للوصول إلى مورد معين. يمكنك تنفيذ منطق الترخيص في معالجات الطلبات الخاصة بك لتقييد الوصول بناءً على أدوار المستخدم أو أذوناته.

أفضل ممارسات الأمان:

النشر

يتضمن نشر تطبيق Tornado عدة خطوات، بما في ذلك تكوين خادم ويب، وإعداد مدير عمليات، وتحسين الأداء.

خادم الويب:

يمكنك نشر Tornado خلف خادم ويب مثل Nginx أو Apache. يعمل خادم الويب كوكيل عكسي (reverse proxy)، حيث يقوم بإعادة توجيه الطلبات الواردة إلى تطبيق Tornado.

مدير العمليات:

يمكن استخدام مدير عمليات مثل Supervisor أو systemd لإدارة عملية Tornado، مما يضمن إعادة تشغيلها تلقائيًا في حالة تعطلها.

تحسين الأداء:

التدويل (i18n) والتعريب (l10n)

عند بناء تطبيقات لجمهور عالمي، من المهم مراعاة التدويل (i18n) والتعريب (l10n). التدويل هو عملية تصميم تطبيق بحيث يمكن تكييفه مع مختلف اللغات والمناطق دون تغييرات هندسية. التعريب هو عملية تكييف تطبيق مدوّل للغة أو منطقة معينة عن طريق إضافة مكونات خاصة باللغة المحلية وترجمة النصوص.

Tornado و i18n/l10n

لا يحتوي Tornado نفسه على مكتبات مدمجة للتدويل/التعريب. ومع ذلك، يمكنك بسهولة دمج مكتبات بايثون القياسية مثل `gettext` أو أطر عمل أكثر تطوراً مثل Babel للتعامل مع التدويل/التعريب داخل تطبيق Tornado الخاص بك.

مثال باستخدام `gettext`:

1. **إعداد اللغات المحلية الخاصة بك:** أنشئ أدلة لكل لغة تريد دعمها، تحتوي على كتالوجات الرسائل (عادةً ملفات `.mo`).

locales/
 en/LC_MESSAGES/messages.mo
 fr/LC_MESSAGES/messages.mo
 de/LC_MESSAGES/messages.mo

2. **استخراج السلاسل النصية القابلة للترجمة:** استخدم أداة مثل `xgettext` لاستخراج السلاسل النصية القابلة للترجمة من كود بايثون الخاص بك إلى ملف `.po` (Portable Object). سيحتوي هذا الملف على السلاسل الأصلية والعناصر النائبة للترجمات.

xgettext -d messages -o locales/messages.po your_tornado_app.py

3. **ترجمة السلاسل النصية:** ترجم السلاسل النصية في ملفات `.po` لكل لغة.

4. **تجميع الترجمات:** قم بتجميع ملفات `.po` إلى ملفات `.mo` (Machine Object) التي يستخدمها `gettext` في وقت التشغيل.

msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo

5. **التكامل مع تطبيق Tornado الخاص بك:**

import gettext
import locale
import os
import tornado.web

class BaseHandler(tornado.web.RequestHandler):
 def initialize(self):
  try:
  locale.setlocale(locale.LC_ALL, self.get_user_locale().code)
  except locale.Error:
  # معالجة الحالات التي لا يدعمها النظام
  print(f"Locale {self.get_user_locale().code} not supported")

  translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
  translation.install()
  self._ = translation.gettext

 def get_current_user_locale(self):
  # منطق لتحديد لغة المستخدم (على سبيل المثال، من ترويسة Accept-Language، إعدادات المستخدم، إلخ)
  # هذا مثال مبسط - ستحتاج إلى حل أكثر قوة
  accept_language = self.request.headers.get('Accept-Language', 'en')
  return tornado.locale.get(accept_language.split(',')[0].split(';')[0])

class MainHandler(BaseHandler):
 def get(self):
  self.render("index.html", _=self._)

settings = {
 "template_path": os.path.join(os.path.dirname(__file__), "templates"),
}

app = tornado.web.Application([
 (r"/", MainHandler),
], **settings)

6. **تعديل قوالبك:** استخدم الدالة `_()` (المرتبطة بـ `gettext.gettext`) لوضع علامة على السلاسل النصية للترجمة في قوالبك.

<h1>{{ _("Welcome to our website!") }}</h1>
<p>{{ _("This is a translated paragraph.") }}</p>

اعتبارات هامة للجماهير العالمية:

مواضيع متقدمة

صفحات الخطأ المخصصة:

يمكنك تخصيص صفحات الخطأ التي يعرضها Tornado عند حدوث خطأ. يتيح لك ذلك توفير تجربة أكثر سهولة في الاستخدام وتضمين معلومات تصحيح الأخطاء.

الإعدادات المخصصة:

يمكنك تحديد إعدادات مخصصة في تكوين تطبيقك والوصول إليها في معالجات الطلبات الخاصة بك. هذا مفيد لتخزين المعلمات الخاصة بالتطبيق، مثل سلاسل اتصال قاعدة البيانات أو مفاتيح API.

الاختبار:

اختبر تطبيقات Tornado الخاصة بك جيدًا للتأكد من أنها تعمل بشكل صحيح وآمن. استخدم اختبارات الوحدة واختبارات التكامل واختبارات النهاية إلى النهاية لتغطية جميع جوانب تطبيقك.

الخاتمة

Tornado هو إطار عمل ويب قوي ومتعدد الاستخدامات ومناسب تمامًا لبناء تطبيقات ويب قابلة للتطوير وعالية الأداء. إن بنيته غير المتزامنة ودعمه لـ WebSocket وواجهة برمجة التطبيقات سهلة الاستخدام تجعله خيارًا شائعًا للمطورين في جميع أنحاء العالم. باتباع الإرشادات والأمثلة الواردة في هذا الدليل الشامل، يمكنك البدء في بناء تطبيقات Tornado الخاصة بك والاستفادة من ميزاته العديدة.

تذكر مراجعة وثائق Tornado الرسمية للحصول على أحدث المعلومات وأفضل الممارسات. برمجة سعيدة!