13. تمرين [IMPOTS] باستخدام خدمة WEB
نعود إلى التمرين [IMPOTS] الذي تمت مناقشته سابقًا في الفقرات 4.2 و4.3 و8 و10.
![]() |
13.1. الخادم
نضع أنفسنا في بنية العميل-الخادم التالية:
![]() |
على جانب الخادم، سنستخدم مرة أخرى بنية ثلاثية الطبقات. سيتم تنفيذ الطبقة [dao] بواسطة الفئة ImpotsMySQL المستخدمة في الإصدار الذي يتضمن SGBD وMySQL في الفقرة 10. سيتم تنفيذ الطبقة [metier] بواسطة الفئة [ImpotsMetier] التي تمت دراستها سابقًا. وبالتالي، لم يتبقَ سوى كتابة خدمة الويب. تتلقى هذه الخدمة من عملائها معلمة params بالصيغة params= oui,2,200000، حيث يشير العنصر الأول إلى ما إذا كان دافع الضرائب متزوجًا أم لا، والثاني إلى عدد أطفاله، والثالث إلى راتبه السنوي.
خدمة الويب هي كما يلي (impots_web_01):
#!D:\Programs\ActivePython\Python2.7.2\python.exe
# -*- coding=Utf-8 -*-
# استيراد الوحدة النمطية للفئات Impots*
from impots import *
import cgi,cgitb,re
# السماح بعرض معلومات التصحيح
cgitb.enable()
sys.stderr=sys.stdout
# ------------------------------------------------
# خدمة الويب الخاصة بالضرائب
# ------------------------------------------------
# تم وضع البيانات اللازمة لحساب الضريبة في الجدول mysqL TABLE
# التابعة لقاعدة البيانات BASE. الجدول له البنية التالية
# حدود decimal(10,2)، coeffR decimal(6,2)، coeffN decimal(10,2)
# معلمات الأشخاص الخاضعين للضريبة (الحالة الاجتماعية، عدد الأبناء، الراتب السنوي)
# يتم إرسالها من قبل العميل بالصيغة params=الحالة الاجتماعية، عدد الأبناء، الراتب السنوي
# يتم إرجاع النتائج (الحالة الاجتماعية، عدد الأبناء، الراتب السنوي، الضريبة المستحقة) إلى العميل
# بالصيغة <ضريبة>القيمة</ضريبة>
# أو في شكل <خطأ>رسالة</خطأ>، إذا كانت المعلمات غير صالحة
# يرسل الخادم نصًا غير منسق إلى العميل
print "Content-Type: text/plain\n"
# تعريف الثوابت
USER="root"
PWD=""
HOTE="localhost"
BASE="dbimpots"
TABLE="impots"
# يتم إنشاء الطبقة [metier]
# يبدو أن لغة Python لا تدعم الجلسات
# في PHP، كنا سنستخدم جلسة عمل لتخزين الكائن الخاص بالمجال
# هنا، يتم إنشاؤه بشكل منهجي استنادًا إلى بيانات قاعدة البيانات MySQL
# إنشاء مثيل لطبقة [metier]
try:
metier=ImpotsMetier(ImpotsMySQL(HOTE,USER,PWD,BASE,TABLE))
except (IOError, ImpotsError) as infos:
print ("<erreur>Une erreur s'est produite : {0}</erreur>".format(infos))
sys.exit()
# نسترد السطر الذي أرسله العميل إلى الخادم
params=cgi.FieldStorage().getlist('params')
# إذا لم تكن هناك معلمات، فسيحدث خطأ
if not params:
print "<erreur>Le parametre [params] est absent<erreur>"
sys.exit()
# يتم معالجة المعلمة params
items=params[0].strip().lower().split(',')
# يجب ألا يكون هناك سوى 3 حقول
if len(items)!=3:
print "<erreur>[%s] : nombre de parametres invalide</erreur>" % (params[0])
sys.exit()
# يجب أن يكون المعلمة الأولى (الحالة الاجتماعية) نعم/لا
marie=items[0].strip()
if marie!="oui" and marie != "non":
print "<erreur>[%s] : 1er parametre invalide</erreur>\n"% (params[0])
sys.exit()
# يجب أن يكون المعلمة الثانية (عدد الأطفال) عددًا صحيحًا
match=re.match(r"^\s*(\d+)\s*$",items[1])
if not match:
print "<erreur>[%s] : 2ieme parametre invalide</erreur>\n"% (params[0])
sys.exit()
enfants=int(match.groups()[0])
# يجب أن يكون المعلمة الثالثة (الراتب) عددًا صحيحًا
match=re.match(r"^\s*(\d+)\s*$",items[2])
if not match:
print "<erreur>[%s] : 3ieme parametre invalide</erreur>\n"% (params[0])
sys.exit()
salaire=int(match.groups()[0])
# يتم حساب الضريبة
impot=metier.calculer(marie,enfants,salaire)
# يتم إرجاع النتيجة
print "<impot>%s</impot>\n" % (impot)
# النهاية
ملاحظات:
- السطر 5: يتم استيراد الكائنات من الملف impots.py؛
- السطر 9: قد يكون تصحيح أخطاء البرنامج النصي Cgi أمرًا صعبًا. تقوم الوحدة النمطية cgitb، في حالة حدوث خطأ، بإرسال سبب التعطل. وللقيام بذلك، يجب إعادة توجيه مخرج الأخطاء القياسي (sys.stderr) إلى المخرج القياسي (sys.stdout) (السطر 10)؛
- السطر 26: رأس Http الذي يحدد طبيعة المستند المرسل، وهو هنا نص غير منسق. ترسل خدمة الويب ردها في شكل سطر نصي واحد:
- <erreur>message</erreur> في حالة وجود خطأ؛
- <impot>valeur</impot> حيث يمثل valeur مبلغ الضريبة.
- السطر 43: إنشاء مثيلات الطبقات [dao] و [metier]؛
- الأسطر 44-46: في حالة حدوث خطأ في إنشاء المثيل، يرسل البرنامج النصي استجابته وينتهي؛
- الأسطر 49-53: يتم استرداد المعلمة 'params'. إذا كانت غائبة، يرسل البرنامج النصي استجابته وينتهي؛
- السطر 56: يتم تقسيم المعلمة 'oui,2,200000' إلى 3 حقول في المصفوفة items؛
- الأسطر 58-77: يتم التحقق من صحة الحقول الثلاثة. في حالة وجود خطأ، يرسل البرنامج النصي إجابته وينتهي؛
- السطر 79: يتم حساب الضريبة؛
- السطر 81: ويتم إرسالها إلى العميل.
في متصفح الويب، نحصل على النتائج التالية:
![]() | ![]() |
13.2. عميل مبرمج
البرنامج (client_impots_web_01)
# -*- coding=utf-8 -*-
import httplib,urllib,re
# الثوابت
HOST="localhost"
URL="/cgi-bin/impots_web_01b.py"
data=("oui,2,200000","non,2,200000","oui,3,200000","non,3,200000","x,y,z,t","x,2,200000", "oui,x,200000","oui,2,x");
# تسجيل الدخول
connexion=httplib.HTTPConnection(HOST)
# المتابعة
#connexion.set_debuglevel(1)
# يتم تكرار البيانات المراد إرسالها إلى الخادم
for params in data:
# يجب ترميز المعلمات قبل إرسالها إلى الخادم
parametres = urllib.urlencode({'params': params})
# إرسال الطلب
connexion.request("POST",URL,parametres)
# معالجة الرد (سطر نصي)
reponse=connexion.getresponse().read()
lignes=reponse.split("\n")
# سطر النص بالصيغة التالية
# <impot>xxx</impot>
# أو <erreur>xxx</erreur>
impot=re.match(r"^<impot>(\S+)</impot>\s*$",lignes[0])
if impot:
print "params=%s, impot=%s" % (params,impot.groups()[0])
else:
erreur=re.match(r"^<erreur>(.+)</erreur>\s*$",lignes[0])
if erreur:
print "params=%s, erreur=%s" % (params,erreur.groups()[0])
else:
print lignes
# إغلاق الاتصال
connexion.close()



