الصنف 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 في توثيق بايثون الرسمي.