الصنف cgi.FieldStorage‎‎ في بايثون

من موسوعة حسوب
اذهب إلى: تصفح، ابحث


يمكن الوصول إلى البيانات المرسلة إلى المخدّم عن طريق الصنف FieldStorage، وإن كان النموذج يتضمّن حروفًا بترميز غير ترميز ASCII فيمكن استخدام المعامل المفتاحي encoding لتعيين قيمة الترميز المستخدم في الملف الحاوي على النموذج، ويمكن الوصول إلى الترميز المستخدم عادة في الوسم META في قسم HEAD من ملف HTML أو عن طريق الترويسة Content-Type).

يقرأ الصنف محتويات النموذج من المدخلات القياسية أو من البيئة (بالاعتماد على قيمة عدد من متغيرات البيئة والمعيّنة حسب معايير CGI). قد يستهلك الصنف المدخلات القياسية؛ لذا يجب تهيئته مرة واحدة فقط.

تشبه نسخ الصنف FieldStorage قواميس بايثون إلى حدّ كبير، إذ يمكن فهرسة الكائن كما هو الحال مع القواميس، ويمكن اختبار وجود عنصر معيّن باستخدام المعامل in، ويدعم الكائن كذلك استخدام التابع keys()‎ الخاصّ بالقواميس إضافة إلى الدالة الداخلية len()‎. لا تظهر حقول النموذج التي تتضمّن سلاسل نصية فارغة في القاموس وسيجري تجاهلها، وللإبقاء على مثل هذه القيم، يجب إعطاء المعامل المفتاحي keep_blank_values القيمة True عند إنشاء نسخة من الصنف FieldStorage.

فعلى سبيل المثال تتحقّق الشيفرة التالية (والتي تفترض أنّ الترويسة Content-Type والسطر الفارغ قد طُبعا مسبقًا) من أن الحقلين name و addr هما حقلان لا يحتويان على سلاسل نصية فارغة:
form = cgi.FieldStorage()
if "name" not in form or "addr" not in form:
    print("<H1>Error</H1>")
    print("Please fill in the name and addr fields.")
    return
print("<p>name:", form["name"].value)
print("<p>addr:", form["addr"].value)
...further form processing here...
الحقول في هذه الشيفرة والتي تم الوصول إليها باستخدام العبارة form[key]‎ هي بحدّ ذاتها نسخ من الكائن FieldStorage (أو MiniFieldStorage وذلك حسب ترميز النموذج). يمكن الوصول إلى قيمة الحقل النصية باستخدام الخاصية value في نسخ الكائن، ويعيد التابع getvalue()‎ السلسلة النصية مباشرة، ويستقبل كذلك معاملًا آخر اختياريًا يُستخدم لتعيين القيمة التي يعيدها التابع إن لم يكن المفتاح المطلوب موجودًا.

إن تضمّنت البيانات المرسلة من النموذج على حقول متعددة تحمل الاسم ذاته، فإنّ الكائن المستحصل من العبارة form[key]‎ لن يكون كائن FieldStorage أو MiniFieldStorage ولكن قائمة من هذه الكائنات. وكذلك الأمر بالنسبة للتابع form.getvalue(key)‎ إذ سيعيد قائمة من السلاسل النصية في مثل هذه الحالة. إن كنت تتوقع حدوث هذه الحالة (أي عندما يتضمّن نموذج HTML الخاصّ بك على عدد من الحقول التي تحمل الاسم عينه) فاستخدم التابع getlist()‎ والذي يعيد قائمة من القيم دائمًا (وبهذه الصورة لن تضطر إلى التعامل مع الحالات الخاصة التي تتضمّن عنصرًا واحدًا فقط).

تربط الشيفرة التالية أي عدد من الحقول التي تحمل الاسم username ويفصل بين قيمها بفاصلة:
value = form.getlist("username")
usernames = ",".join(value)
إن كان الحقل يمثّل ملفًّا مرفوعًا، فإنّ الوصول إلى قيمة الحقل باستخدام الخاصية value أو باستخدام التابع getvalue()‎ سيؤدي إلى قراءة الملف بأكمله في الذاكرة على هيئة بايتات، وقد يكون هذا أمرًا غير مرغوب به؛ لذا يمكن التحقّق من رفع الملف إما باختبار الخاصية filename أو الخاصية file، ثم يمكن بعد ذلك قراءة البيانات من الخاصية file قبل إغلاقه تلقائيًا كجزء من عملية التخلص من نسخة الصنف FieldStorage (القيمة المعادة من التابعين read()‎ و readline()‎ هي البايتات):
fileitem = form["userfile"]
if fileitem.file:
    # It's an uploaded file; count lines
    linecount = 0
    while True:
        line = fileitem.file.readline()
        if not line: break
        linecount = linecount + 1
يمكن استخدام كائنات FieldStorage مع عبارات with، والتي ستغلق هذه الكائنات عند انتهاء عمل العبارة.

تعين القيمة ‎-1 للخاصية done في الكائن عند حدوث خطأ أثناء جلب محتويات الملف المرفوع (عندما يقاطع المستخدم عملية إرسال النموذج بضغطه لزر الرجوع أو زر الإلغاء مثلًا).

تتيح مسوّدة معيار رفع عدد من الملفات باستخدام حقل واحد (باستخدام الترميز multipart/*‎)، فإنّ العناصر المستحصلة تكون على هيئة كائن FieldStorage شبيه بالقاموس. ويمكن التحقّق من حدوث هذه الحالة بواسطة الخاصية type، والتي يجب أن تكون multipart/form-data (أو أيّ نوع MIME آخر يطابق العبارة multipart/*‎)، وفي هذه الحالة يمكن المرور على عناصر الكائن تعاوديًا كما هو الحال مع كائن النموذج الأساسي.

إذا أرسل النموذج إلى المخدّم بالأسلوب القديم (كسلسلة استعلام نصية أو كبيانات ذات جزء واحد من نوع application/x-www-form-urlencoded) فإنّ العناصر ستكون نسخًا من الصنف MiniFieldStorage. وفي هذه الحالة تحمل الخصائص list و file و filename القيمة None دائمًا.

يتضمّن النموذج المرسل بطريقة POST والذي يضمّ سلسلة استعلام نصية أيضًا عناصر FieldStorage و MiniFieldStorage.

ملاحظات:

  • تُغلَق الخاصية file تلقائيًا عند التخلص من كائن FieldStorage التابعة له في الإصدار 3.4 من بايثون.
  • أصبح الصنف FieldStorage داعمًا لبروتوكول إدارة السياق context management في الإصدار 3.5 من بايثون.

توابع الصنف FieldStorage

 التابع FieldStorage.getfirst()‎

يعيد هذا التابع قيمة واحدة دائمًا ترتبط بالحقل الذي يحمل الاسم المعطى.

التابع FieldStorage.getlist()‎

يعيد هذا التابع دائمًا قائمة بالقيم المرتبطة بالحقل المعطى.

مصادر

صفحة Common Gateway Interface support في توثيق بايثون الرسمي.