أعجوبة

البرمجيات الحُرة والمفتوحة المصدر

أدوات المستخدم

أدوات الموقع


okasha:sample1

اختلافات

عرض الاختلافات بين النسخة المختارة و النسخة الحالية من الصفحة.

رابط إلى هذه المقارنة

جانبي المراجعة السابقةالمراجعة السابقة
المراجعة التالية
المراجعة السابقة
okasha:sample1 [2010/02/10 22:47] alsadiokasha:sample1 [2015/04/23 03:21] (حالي) – تحرير خارجي 127.0.0.1
سطر 1: سطر 1:
 +====== مثال أولي بسيط ======
 +إن غالبية دوال وصنوف عكاشة موثّقة جيّداً لذا يمكنك استعمال pydoc للوصول لها.
 +
 +كذلك يمكنك استعمال المثال [[http://git.ojuba.org/cgit/okasha/tree/test.py|test.py]] الموجود في كود عكاشة فهو يوضّح أغلب استخدامات عكاشة.
 +
 +بعكس ذاك المثال المسهب فإن هذه الوثيقة ستعلّمك كيف تعمل مشروع بدهي مثل "مرحبا، يا عالم!"
 +
 +وقبل أن تبدأ تخلّص من الخوف فأغلب الكود هو تعليقات (مجرد شرح).
 +
 +===== كيف نبدأ ؟ =====
 +أنشء مجلّد للمشروع. وإن لم تكن الاعتماديات((الاعتماديات التي نحتاجها في هذا المثال هي عكاشة و python-paste فقط)) مثبّتة في النظام أو كنت تريد أن يكون التطبيق الخاص بك قابل للنقل portable إلى أجهزة لا تضمن أن يكون عكاشة وبقية الاعتماديات مثبّتا فيها كل ما عليك هو وضع نسخة من تلك الحزم داخل مجلد المشروع الحالي.
 +
 +بعكس أطر الويب الأخرى تطبيق الويب هو مجرّد ملف واحد به صنف واحد 
 +لذا اعمل ملف سمّه مثلا myapp.py ولتكن محتوياته كما يلي:
 +<code python>
 +#! /usr/bin/python
 +# -*- coding: UTF-8 -*-
 +"""
 +this is my first okasha web app
 +"""
 +from okasha.baseWebApp import *
 +
 +class MyApp(baseWebApp):
 +  def __init__(self, *args, **kw):
 +    baseWebApp.__init__(self,*args, **kw)
 +</code>
 +
 +وبهذا نكون قد أنهينا أول تطبيق لنا
 +
 +===== كيف نشغّل هذا التطبيق ؟ =====
 +هناك عدّة طرق لإطلاق تطبيقات عكاشة. أسهلها وأفضلها خلال فترة التطوير هو استعمال حزمة python-paste
 +
 +يمكنك عمل ملف منفصل اسمه serve.py مثلا يقوم على تشغيل التطبيق الخاص بك وذلك كما يلي
 +<code python>
 +#! /usr/bin/python
 +# -*- coding: UTF-8 -*-
 +import sys, os, os.path
 +# this requires python-paste package
 +from paste import httpserver
 +from myapp import MyApp
 +
 +d=os.path.dirname(sys.argv[0])
 +application=MyApp(
 +      os.path.join(d,'templates'),
 +      staticBaseDir={'/media/':os.path.join(d,'media')}
 +);
 +httpserver.serve(application, host='127.0.0.1', port='8080')
 +</code>
 +
 +فعند تنفيذ برنامج serve.py أعلاه سيعمل خادم paste الضمني المنضدد على المنفذ 8080 (يمكنك تحديد أي رقم) وسيقبل أي اتصالات من العنوان المحلي 127.0.0.1 . إن كنت تريده أن يستقبل من كل العناوين اجعله 0.0.0.0 للمزيد من الخيارات انظر [[http://pythonpaste.org/modules/httpserver.html|وثائق paste]]
 +
 +بل ويمكن وضع هذا الكود داخل الوحدة التي تحتوي تطبيق الويب نفسه يعني في مثالنا يمكن الاستغناء عن serve.py وذلك بأن نجعل ملف myapp.py كما يلي:
 +
 +<code python>
 +#! /usr/bin/python
 +# -*- coding: UTF-8 -*-
 +"""
 +this is my first okasha web app
 +"""
 +from okasha.baseWebApp import *
 +
 +class MyApp(baseWebApp):
 +    def __init__(self, *args, **kw):
 +      baseWebApp.__init__(self,*args, **kw)
 +
 +if __name__ == '__main__':
 +    # this requires python-paste package
 +    from paste import httpserver
 +    import sys, os, os.path
 +    
 +    d=os.path.dirname(sys.argv[0])
 +    application=MyApp(
 +      os.path.join(d,'templates'),
 +      staticBaseDir={'/media/':os.path.join(d,'media')}
 +    );
 +    httpserver.serve(application, host='127.0.0.1', port='8080')
 +</code>
 +
 +وفي هذه الحالة لا نحتاج ملف serve.py حيث يمكننا إطلاق تطبيق الويب عبر تنفيذ myapp.py حيث أن الجزء في آخر الملف لن ينفّذ في حالة استخدام الملف كوحدة بايثونية (مكتبة) بل عند تنفيذه كبرنامج وليس مكتبة.
 +
 +===== ما معنى الكود ؟ =====
 +في أول البرنامج أول خطوة قمنا بها هي استيراد محتويات إطار الويب عكاشة
 +  from okasha.baseWebApp import *
 +
 +ثم قمنا بتعريف كائن مشتق من تطبيق الويب الأساسي في عكاشة baseWebApp 
 +<code python>
 +class MyApp(baseWebApp):
 +</code>
 +وفيه عرّفنا دالة الاستهلال التي كل مهمّتها هي استدعاء الدالة في الصنف الأساس وتمرير المعاملات له بشكل أعمى (سنشرح هذه المعاملات لاحقا)
 +<code python>
 +  def __init__(self, *args, **kw):
 +    baseWebApp.__init__(self,*args, **kw)
 +</code>
 +
 +يمكنك استقبال معاملات خاصة بك هكذا للاحتفاظ بها لاستخدامها لاحقا هكذا
 +<code python>
 +  def __init__(self, name, *args, **kw):
 +    self.name=name
 +    baseWebApp.__init__(self,*args, **kw)
 +</code>
 +
 +أما كود التشغيل فهو كما يلي:
 +  from paste import httpserver
 +نستورد خادم http من داخل حزمة paste. يستقبل خادم paste تطبيق الويب المتوافق مع WSGI كمعامل أول هكذا 
 +
 +  httpserver.serve(application, host='127.0.0.1', port='8080')
 +
 +حيث application هو تطبيق الويب وهو في حالتنا كائن فرد من الصنف MyApp الذي اشتققناه من تطبيق الويب الأساسي في عكاشة baseWebApp
 +
 +نقوم بعمل هذا الكائن كما نعمل أي متغير أو كائن في بايثون
 +<code python>
 +    d=os.path.dirname(sys.argv[0])
 +    application=MyApp(
 +      os.path.join(d,'templates'),
 +      staticBaseDir={'/media/':os.path.join(d,'media')}
 +    );
 +</code>
 +المتغير d يمثّل المجلّد الذي يحتوي تطبيق الويب
 +وقد قمنا بتحديد مجلد فرعي عنه اسمه templates كي يحتوي القوالب كذلك طلبنا أن تحال كل العناوين التي تبدأ ب /media/ إلى المجلد الفرعي media داخل مجلد التطبيق حيث يمكننا استخدامه لوضع ملفات الصور وملفات css وغيرها من الملفات الساكنة static files.
 +
 +يوفّر عكاشة أكثر من طريقة لتخديم الملفات الساكنة منها أن تمرّر له قاموس staticBaseDir مفاتيحه هي الجزء في بداية العنوان ثم المجلد الذي سيتم البحث عن الملفات فيه (يمكن استخدام أكثر من مجلد)
 +
 +كذلك هناك خاصية أخرى وهي عمل إعادة توجيه redirect لطلبات معيّنة إلى عنوان آخر أو خادم آخر يحتوي تلك الملفات الساكنة.
 +
 +للمزيد انظر وثائق دالة الاستهلال لصنف baseWebApp في كود عكاشة.
 +
 +===== ماذا يفعل هذا التطبيق الخالي ؟ =====
 +سيبحث عكاشة عن الطريقة/الدالة في كائن التطبيق فإن لم يجد  واحدة مناسبة فإنه يستدعي الدالة _root ويمرر لها كائن من الصنف Request يحتوي تفاصيل الطلب ويمرّر له بقية عناصر العنوان.
 +وحيث أنّنا لم نعرّف تلك الدالة فإن دالة _root التلقائية الموجودة في عكاشة تعمل وتظهر لنا في شاشة المتصفح عند زيارة الموقع صفحة html تحتوي
 +
 +  You requested [/]
 +
 +فإن زرنا العنوان http://localhost:8080/hello/omar سيظهر في المتصفح 
 +
 +  You requested [/hello/omar]
 +
 +===== كتابة دالة خاصة بنا =====
 +جرّب إضافة الكود التالي بعد دالة الاستهلال init في صنف MyApp
 +<code python>
 +  @expose()
 +  def _root(self, rq, *args):
 +    return """<html><body>
 +<img src="/media/logo.gif"/>
 +<h1>welcome to my first okasha application</h1>
 +</body></html>"""
 +</code>
 +الكثير من النّاس لا يألَفون استخدام @ أو ما يُسمى decorator 
 +وشرحها في هذه المرحلة غير مناسب لكن اعلم أنها تستدعي دالة خاصة وهي expose موجودة داخل عكاشة تقوم هذه الدالة بتغيير الدالة التي بعدها وهي في مثالنا _root
 +
 +يمكنك أن ترى وثائق دالة expose في كود عكاشة حتى تعرف ما هي المعاملات التي تستقبلها لكن إن استعملتها دون أي معاملات كما فعلنا فهي تعني أننا لن نستعمل أي قوالب بل سنعيد كود html
 +
 +لاحظ أننا استعملنا ملف logo.gif الموجود في media لكن الرابط الذي استخدمناه قد لا يكون صحيحا دائما لأنه إن كان التطبيق يعمل من داخل سابقة ما حيث لا يكون التطبيق مربوط على جذر الخادم بل داخل سابقة هكذا http://myhost/myapp ويكون ذلك مفيدا عندما يكون هناك أكثر من تطبيق على نفس النطاق domain
 +
 +وحتى لا تعيد كتابة الروابط يمكنك استخدام rq.script التي تعيد سابقة التطبيق الخاص بنا (طبعا ستكون نص خالي إن لم يكن هناك سابقة)
 +
 +<code python>
 +  @expose()
 +  def _root(self, rq, *args):
 +    return """<html><body>
 +<img src="%s/media/logo.gif"/>
 +<h1>welcome to my first okasha application</h1>
 +</body></html>""" % rq.script
 +</code>
 +
 +===== التفاعل مع عناوين URL =====
 +<code python>
 +  @expose()
 +  def hello(self, rq, *args):
 +    if not args: s="world"
 +    else: s=args[0]
 +    return """<html><body>
 +<h1>Hello, %s!</h1>
 +</body></html>""" % s
 +
 +  @expose()
 +  def _root(self, rq, *args):
 +    if not args: raise redirectException(rq.script+'/hello/')
 +    elif args[0]=='favicon.ico': redirectException(rq.script+'/media/favicon.ico')
 +    else: raise forbiddenException()
 +</code>
 +في هذا المثال عملنا دالة اسمها hello سيتم تنفيذ هذه الدالة عند زيارة /hello/ أو /hello/Name/ أو ما شابه. هذه الدالة تستلم بقية العنوان على شكل معاملات حيث ستكون قيمة args منظومة خالية [] أو ['Name'] على الترتيب في المثالين.
 +
 +كذلك جعلنا الوصول لجذر التطبيق يحيل إلى العنوان /hello/ الذي بدوره يطبع Hello, world! لأنه لا يوجد تتمة للعنوان (المنظومة خالية)
 +
 +كذلك عملنا تحويلة أخرى داخل _root تحيل من favicon.ico إلى /media/favicon.ico
 +
 +أمّا إن لم يجد دالة مناسبة ولم يحصل أي من الحالتين السابقتين (أي لم نطلب جذر التطبيق ولا favicon) عندها سينفذ ما بعد else وهو في حالتنا رفع الخطأ رقم 403 ممنوع الوصول لتلك الصفحة.
 +
 +يمكنك مكان السطر الأخير كتابة ما يلي
 +
 +    else: raise fileNotFoundException()
 +
 +حتى تحصل على الخطأ 404 (صفحة غير موجودة)
 +
 +كذلك يمكنك تخصيص الصفحة التي تظهر عند حدوث هذين الخطأين عبر تخصيص الدالة _403 و _404
 +
 +===== التفاعل مع النماذج forms =====
 +غيّر الدالة hello لتصبح كما يلي :
 +
 +<code python>
 +  @expose()
 +  def hello(self, rq, *args):
 +    n=rq.q.getfirst('n','world').decode('utf-8')
 +    return """<html><body>
 +<h1>Hello, {0}!</h1>
 +<form name="MyForm">
 +Please enter name:
 +<input name="n" type="text" value="{0}"></input>
 +</form>
 +</body></html>""".format(n)
 +</code>
 +
 +لاحظ استخدامنا ل rq.q.getfirst للحصول على قيمة عنصر من النموذج وهو في حالتنا n وهي ذاتها التي تأتي من مربع النص الذي اسمه n في كود html. إن لم تكن تلك القيمة التلقائية world مكانها
 +
  

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki