اذهب إلى المحتوى

سامح أشرف

الأعضاء
  • المساهمات

    2934
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    56

كل منشورات العضو سامح أشرف

  1. توفر أكاديمية حسوب ضمان لإسترداد كامل سعر الدورة في حالة أنك أنهيت الدورة ولم تجد أي عمل لمدة ستة أشهر (من وقت إتمام الدورة)، وأنا أقتبس هنا من صفحة الأسئلة الشائعة الخاصة بالأكاديمية: ويمكنك أن تبحث عن عمل من خلال مواقع العمل الحر كذلك مثل مستقل وخمسات، وستحصل على إرشادات من مختصين في كيفية تجهيز سيرة ذاتية CV وصفحتك الشخصية على مواقع العمل الحر. كما ستحصل على شهادة مقدمة من الأكاديمية تفيد بأنك أتمت الدورة بالكامل وأنهيت كل مشاريعها، بالإضافة إلى وصول مدى الحياة لمحتوى الدورة حتى بعد تحديثها.
  2. سبب هذا الخطأ هو أنك لم تقم بتنفيذ الإستعلام من الأساس لذلك يتم إرجاع كائن sqlalchemy.BaseQuery وليس قائمة بالمستخدمين، ولحل هذه المشكلة يمكنك أن تستعمل التابع all على النحو التالي: return jsonify(json_list = qryresult.all()) بهذا الشكل يمكنك أن تقوم بإرجاع قائمة المستخدمين. يمكنك أيضًا عمل تسلسل serialize كالتالي: return jsonify(json_list=[i.serialize for i in qryresult.all()])
  3. هذا الأمر يحدث بسبب المحمل Werkzeug والذي يقوم بإنشاء عملية process جديدة للمشروع، لكي يقوم بإغلاق هذه العملية وإعادة تشغيلها عندما يتم تغير أي أكواد خاصة بالمشروع، وبالتالي يتم إعادة تحميل الخادم بسرعة دون الحاجة إلى إعادةى تشغيله يدويًا في كل مرة، وبالتأكيد هذا الأمر يحدث فقط في بيئة التطوير Development Environment ولا يتم إستخدامه في بيئة الإنتاج Production Environment، ويمكنك التأكد من هذا الأمر من خلال قراءة الكود الخاص بالدالة restart_with_reloader في الملف werkzeug/_reloader.py حيث ستجد أنه يتم إستعمال التابع ()subprocess.call للقيام بإنشاء عملية جديدة والتحكم فيها في كل مرة يتم تعديل كود المشروع. تستطيع إيقاف هذا السلوك من خلال تمرير المعامل use_reloader بقيمة Flase إلى التابع app.run كالتالي: if __name__ == '__main__': print('# Starting #') app.run(debug=True, use_reloader=False) و من خلال الأمر flask على النحو التالي: FLASK_DEBUG=1 flask run --no-reload يمكنك أيضًا أن توقف هذا السلوك من خلال تشغيل التطبيق في وضع الإنتاج Production Mode عن طريق إزالة المعامل debug : if __name__ == '__main__': print('# Starting #') app.run() في كل الحالات السابقة لن يعمل التطبيق إلا مرة واحدة، ولكن ستخسر ميزة إعادة تشغيل الخادم بشكل تلقائي وعليك حينها أن تقوم بإعادة تشغيله بشكل يدوي.
  4. يمكنك أن تقوم بهذا الأمر من خلال إستخدام الدالة send_file والتي تقوم بإستقبال مسار الصورة (أو أي ملف) كمعامل أول، ويمكنك تمرير نوع الملف (لكي يتعرف عليه المتصفح ويعرضه بالطريقة الصحيح) من خلال تمرير المعامل mimetype، على النحو التالي: @app.route('/user_image') def user_image(): # ... return send_file('./path/to/image.jpg', mimetype='image/jpeg') بهذا الشكل يمكنك أن تقوم بإعادة صورة (أو أي ملف آخر) بعد التأكد من بيانات المستخدم أو أي شيء آخر.
  5. سبب المشكلة الأولى أنك تقوم بإستخدام ملف باسم flask.py وعندما تستدعي الكائن Flask أو request من المكتبة flask فإن بايثون تحاول إستدعاء هذه الكائنات من هذا الملف flask.py وبالتالي يفشل الكود في العثور على هذه الكائنات، ولحل المشكلة يجب إعادة تسميه الملف لأي شيء آخر غير flask.py مثل app.py الأمر الآخر هو أنك يجب أن تقوم بتثيت flask في البيئة الإفتراضية وليس بشكل عام في نظام التشغيل، وذلك من خلال تفعيل البيئة الإفتراضية source bin/activate ثم تنفيذ الأمر التالي لتثبيت فلاسك Flask: pip install flask الآن يمكنك تشغيل المشروع بدون مشكلة: python app.py أو من خلال الأمر flask: flask run
  6. هل يمكنك إغلاق Android Studio ثم حذف الملف app\build\outputs\apk\app-debug.apk بعد ذلك قم بإعادة محاولة بناء المشروع مرة أخرى. ملاحظة: إن لم تتمكن من حذف الملف فحاول إغلاق المهمة java من مدير المهام Task Manager يمكنك أيضًا محاولة تنفيذ الأمر التالي وإعادة المحاولة: flutter clean
  7. تطبيقات فلاسك Flask تحتاج لإضافة كل الملفات من نوع Static مثل ملفات CSS و ملفات JavaScript إلى مجلد باسم static والوصول إلى هذه الملفات من خلال الدالة url_for وتمرير القيمة static إليها كمعامل أول ومسار الملف المراد تحميله داخل المجلد static، وبالتالي ستكون بنية المشروع على النحو التالي: /app - app_runner.py /services - app.py /templates - home.html /static /styles - style.css أما في الملف home.html فيجب أن تقوم بتعديل مسار الملف ليكون كالتالي: <link rel="stylesheet" href="{{ url_for('static', filename='styles/style.css') }}"> أو إذا كان ملف JavaScript: <script srd="{{ url_for('static', filename='js/script.js') }}"></script>
  8. تحدث هذه المشكلة لأنك لم تقم بتثبيت الحزمة python-mysql بشكل صحيح، يمكنك تثبيتها من خلال الأمر التالي: sudo apt-get install python-mysqldb أيضًا يمكنك أن تستعمل الحزمة pymysql والتي سوف تؤدي نفس الغرض وتستطيع تثبيتها من خلال الأمر التالي: pip install pymysql ثم يجب تعديل إعدادات المشروع من خلال تغير مسار قاعدة البيانات، على النحو التالي: SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://.....'
  9. تستطيع إستخدام التابع ()request.get_data والذي يتم إستخدامه من قِبل كلٍ من request.data و request.form و request.json حيث يتم جلب البيانات وعمل parse لها حسب قيمة الترويسة content-type في رأس الطلب على سبيل المثال إن كانت قيمة الترويسة Content-Type تحمل أي قيمة من القيم التالية: multipart/form-data application/x-www-form-urlencoded application/x-url-encoded فسوف يتم جلب البيانات وتحليلها وتخزينها في request.form، وستكون قيمة كلٍ من reqeust.data و request.json فارغة حينها. يمكنك إستعمال التابع ()request.get_data على النحو التالي: @app.route('/', methods=['POST']) def index(): print(request.get_data()) # ... لاحظ أنك إن إستعملت أيًا من التوابع request.data و request.form و request.json فسوف يقوم التابع ()request.get_request بإرجاع قيمة فارغة، لذلك عليك أن تقوم بتخزين جسم الطلب في متغير في بداية الدالة.
  10. يمكنك حل هذه المشكلة من خلال تثبيت الحزمة flask-cors والتي سوف تقوم بضبط إعدادات CORS في مشروعك، لتثبيت الحزمة أستخدم الأمر التالي: pip install -U flask-cors الآن يمكنك إستخدامها في الكود على النحو التالي: from flask import Flask from flask_cors import CORS, cross_origin app = Flask(__name__) # إعداد الحزمة cors = CORS(app) app.config['CORS_HEADERS'] = 'Content-Type' @app.route("/") @cross_origin() # أضف هذا السطر لكل المسارات التي تريد الوصول إليها عبر Ajax def index(): return "Home Page" يمكنك أيضًا أن تستخدم دالة لتقوم بتعديل قيمة الترويسة header التي تحمل الاسم Access-Control-Allow-Origin لتكون قيمتها * لكل المسارات من خلال الكود التالي: @app.after_request def after_request(response): header = response.headers header['Access-Control-Allow-Origin'] = '*' return response بهذا الشكل سوف يتم إيقاف CORS لكن لا ينصح بهذا الأمر لأن الموقع قد يتعرض لهجمات تزوير الطلبات من قِبل بعض المخترقين Hackers.
  11. لتتعلم برمجة وتصميم قوالب ووردبريس عليك أولًا تعلم بعض الأساسيات مثل لغات الواجهات الأمامية HTML و CSS و JavaScript وبعد ذلك عليك تعلم اللغة المستخدمة في إنشاء ووردبريس والقوالب الخاصة به (لغة PHP)، بعد ذلك يجب أن تنتقل لتعلم قواعد البيانات MySQL التي يستعمل ووردبريس لتخزين البيانات والإعدادات، ثم عليك أن تعلم كيف يعمل ووردبريس وما هي مكوناته، وهذه المقالة سوف تساعدك على في هذا الأمر: يمكنك أيضًا أن تستخدم بعض الأداوات التي قد تساعدك في عملية التطوير مثل SCSS/LESS التي ستجعلك تكتب كود CSS أقصر وأكثر وضوحًا، أو Grunt/Gulp لمراقبة تعديلات الملفات وتنفيذ مختلف المهام عند استيفاء المتطلبات، أو أداوات التحكم في الإصدارات Versions Control مثل Git وإستخدام مواقع لتخزين المستودعات مثل GitHub. ستجد العديد من المقالات لشرح كل التقنيات السابقة وأكثر بالتفصيل في الأكاديمية من هنا. كما ستجد سلسلة من المقالات باسم "تطوير ووردبريس للمبتدئين" والتي تحتوي على شرح كل ما تريده في ووردبريس. وللحصول على مصادر أكثر تستطيع الإطلاع على هذه المساهمة هنا في حسوب IO.
  12. فلاسك Flask يقوم بتخزين كل المسارات في app.url_map والذي هو عبارة عن مثيل من الكائن werkzeug.routing.Map ، ويمكنك المرور على كل مسار من خلال إستخدام التابع iter_rules، على النحو التالي: from flask import Flask, request, url_for, Response app = Flask(__name__) @app.route('/users/<user_id>') def index(user_id): pass @app.route('/foo') def foo(): routes = [] for rule in app.url_map.iter_rules(): routes.append(rule.endpoint) print(routes) # ['foo', 'static', 'index'] return "printed routes", 200 app.debug = True app.run(debug=True) بهذا الشكل يمكنك الحصول على كل المسارات. كما يمكنك أن تقوم بالحصول على المسارات من خلال سطر الأوامر عبر إستدعاء ملف المشروع الرئيسي وطباعة قيمة app.url_map: python >>> from app import app >>> app.url_map ['foo', 'static', 'index'] أيضًا تستطيع تنفيذ الأمر flask routes للحصول على قائمة من المسارات وأنواعها: > flask routes Endpoint Methods Rule -------- ------- ----------------------- foo GET /foo index GET /users/<user_id> static GET /static/<path:filename>
  13. يوفر الكائن query التابع filter_by والتابع filer ، ويمكن إستخدام أي منهما للقيام بهذه المهمة، على النحو التالي: التابع filter: User.query.filter(User.id == 123).delete() التابع filter_by: User.query.filter_by(id=123).delete() لكن إن كان الجدول users مرتبط بجدول آخر ويتم إعداد إستخدام CASCADE في العلاقة، فعليك أن تستخدم الطريقة الموجودة في سؤال أو الطريقة التالية: user = db.session.query(User).filter(User.user_id==123).first() db.session.delete(user) كما يجب أن تقوم بعمل commit لهذه التغيرات من خلال السطر التالي: db.session.commit() لمزيد من المعلومات عن التابع filter يمكنك أن تلقي نظرة على هذه المقالات هنا:
  14. بالتأكيد، يوفر فلاسك Flask طريقة لتعديل الـ headers قبل إرسال الرد response إلى العميل وذلك من خلال إستخدام Response.headers، كالتالي: from flask import Response @app.route('/home') def home(): xml = '<foo>content</foo>' r = Response(response=xml, status=200, mimetype="application/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r كما أن الكائن Response يقبل معامل باسم content_type لتغير نوع البيانات الموجودة في الرد response، ويمكنك إستخدامها كالتالي: r = Response(response=xml, content_type='text/xml; charset=utf-8') أيضًا فلاسك Flask يقبل إرجاع قائمة من الكائنات عند إستخدام return في نهاية المسار، حيث يكون العنصر الأول في هذه القائمة عبارة عن المحتوى المراد إرجاعه إلى العميل، والعنصر الثاني هو رقم حالة الطلب request status code، والعنصر الثالث هو ترويسات الرد response headers، على النحو التالي: from flask import Response @app.route('/home') def home(): xml = '<foo>content</foo>' return xml, 200, {'Content-Type': 'text/xml; charset=utf-8'}
  15. هناك فرق بين إستخدام session و JWT ولكل منها إستخداماته، في بعض الحالات يكون إستخدام الجلسات session مثل المواقع البسيطة التي تستخدم خادم واحد فقط ولا تحتاج إلى عمل API خاص يحتاج إلى عملية مصادقة. على الجانب الآخر فإن إستخدام JWT يكون مفيد عندما يكون للموقع أكثر من خادم (مثل كل المواقع الكبيرة التي تقوم بتخزين ملفاتها وبياناتها في أكثر من دولة)، وبالتالي لا يمكن التحقق من session id الخاص بالمستخدم لأنه يتم تخزينه على خادم واحد وسيكون من الصعب مشاركته إلى أكثر من خادم، وهنا يأتي دور JWT حيث يتم تشفير بعض البيانات بإستخدام Secret Key ويتم تخزين هذا الرمز token على جهاز العميل (في المتصفح في شكل Cookies أو Local Storage) وكلما قام المستخدم بطلب أحد الصفحات يتم التأكد من الرمز token من خلال فك تشفيره. هنا شرح لكيف تعمل الجلسات Session، وكذلك تقينة Json-Web-Token (JWT): الجلسات Sessions يمكنك أن تتخيل أن الجلسة session عبارة عن مصفوفة من البيانات كالتالي: $session = [ "session_id" => "123456", "user_id" => "q1w2e3", "user_name" => "Sameh" ]; من الكود السابق يتضح أن الجلسة عبارة عن مجموعة من البيانات (مثل اسم المستخدم والمعرف الخاص به id) ويتم توليد id لهذه الجلسة session id بشكل عشوائي، وعندما يقوم أحد المستخدمين بتسجيل الدخول إلى الموقع، يقوم الخادم بتوليد هذه المصفوفة من البيانات (الجلسة session) ويقوم بحفظها في أحد الأماكن (ملف أو قاعدة بيانات أو memcached / redis أو حتى في مصفوفة في الذاكرة)، ثم يتم إرسال معرف الجلسة session id إلى المستخدم ليتم تخزينة في المتصفح في أحد الـ Cookies (تتم هذه العملية تلقائيًا في أغلب الأحيان). الآن يوجد لدينا session في الذاكرة ويوجد لدى العميل session id يتم إرساله بشكل تلقائي مع كل طلب، ويقوم الخادم بالتأكد من وجود جلسة session بهذا الـ id وإذا وجدها يقوم بالسماح بإكمال الطلب وإذا لم يجد أي جلسة لها هذا المعرف id يتم تحويل المستخدم لصفحة تسجيل الدخول ليحصل على جلسة جديدة. هنا صورة قد توضح كيف تتم العملية بالكامل بشكل مبسط: الآن ماذا سوف يحدث إذا قام أحد المخترقين بسرقة معرف الجلسة من متصفح العميل وقام بزراعة هذه البيانات في المتصفح الخاص به (متصفح الهاكر) ثم قام بإرسال بعض الطلبات إلى الخادم على أساس أنه هو العميل الحقيقي؟ سوف تتم كل الطلبات بشكل سليم وسوف يستطيع المخترق بأن يقوم بكل العمليات بدون أي صعوبة، وهذه الطريقة تم إستخدامها على نطاق واسع خلال الأشهر الماضية لسرقة العديد من قنوات اليويتيوب الكبيرة، وذلك من خلال إختراق المتصفح الخاص به (عبر تثبيت أحد البرامج أو الإضافات) والحصول على الـ Cookies الخاصة ببعض المواقع، تسمى هذه الطريقة في الإختراق بـ session hijacking. ماذا سوف يحدث إذا كان لدى الموقع أكثير من خادم لحفظ البيانات مثل المواقع الكبيرة التي تحتاج إلى أكثر من خادم لحفظ البيانات؟ لن يمكننا إستخدام الجلسات بشكل مباشر لأن بيانات الجلسة الواحدة يتم تخزينها في ذاكرة أحد الخاودم (أو في قاعدة البيانات) ولا يمكن أن تتم مشاركتها إلى كل الخوادم، وبالتالي يجب أن يكون هناك خادم خاص بتخزين بيانات الجلسات ويقوم كل خادم بالإتصال به والتأكد من الجلسة في كل طلب مما سوف يؤثر على أداء التطبيق بشكل عام. يمكنك معرفة المزيد عن الجلسات Session من خلال موسوعة حسوب من هنا (الجلسات في Laravel) و من هنا (الدالة session_start في php) رمز JWT رمز JWT يعمل بطريقة مختلفة بعض الشيء، فعندما يقوم المستخدم بتسجيل الدخول، يقوم الخادم بتوليد رمز Token ويرسله إلى المستخدم وفي كل طلب يرسله العميل يجب أن يرسل معه هذا الرمز ليقوم الخادم بفك تشفير هذا الرمز والتحقق من المستخدم، وتتم هذه العملية بالكامل بدون تخزين أي رموز token في الذاكرة أو في قاعدة بيانات. هنا صورة توضح الطريقة التي تعمل بها رموز JWT: ما هي مكونات رمز JWT يتكون الرمز من ثلاثة أجزاء على النحو التالي: رأس Header: يحتوي على الخوارزمية المستعملة في التشفير ونوع الرمز: { "alg": "HS256", "typ": "JWT" } حمولة payload: تحتوي على بيانات المستخدم (بدون كلمة المرور): { "user_id": "1234567890", "name": "John Doe", "iat": 1516239022 } توقيع signature: يحتوي على ناتج تشفير كلًا من الرأس header والحمولة payload بإستخدام خوارزمية مثل HMAC-SHA256 بإستخدام Secret Key (يمكن إعتبارها كـكلمة سر خاصة بالخادم فقط، ولا يتم الكشف عنها بأي شكل من الأشكال) ويكون الناتج في النهاية بالشكل التالي: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c وإذا تم تغير أي جزء من البيانات سوف تحصل على رمز مختلف كليًا، وهذا الأمر يضمن سلامة البيانات وأنه لم يتم التلاعب بها قبل إرسالها. يمكنك إستخدام الموقع jwt.io لتجربة كيف يعمل JWT وتجربة تغير أي جزء من البيانات وملاحظة الرمز الذي يتم توليده. عندما يستقبل الخادم هذا الرمز يقوم بإستخدام نفس الخوارزمية ولكن لفك تشفير الرمز بإستخدام Secret Key، وإذا تمت عملية فك التشفير بنجاح نكون قد نجحنا في التحقق من المستخدم. الآن ماذا سوف يحدث إذا كان الموقع يستعمل أكثر من خادم لإدارة البيانات؟ سوف يعمل كل شيء على مايرام لأن الخادم يقوم بفك تشقير الرمز الذي يصل إليه من المستخدم ولا يحتاج إلى قاعدة بيانات مشتركة لتخزين بيانات الجلسة أو أي شيء من هذا القبيل. ماذا سوف يحدث إذا قام أحد المخترقين بالوصول إلى رمز JWT الموجود لدى أحد المستخدمين؟ سوف يكون بأمكان المخترق عمل كل الطلبات وكأنه هو المستخدم الحقيقي، ولحل هذه المشكلة يتم جعل الرمز صالح لفترة قصيرة للغاية (بضع دقائق فقط) ويتم إنشاء Refresh Token (رمز يستخدم للحصول على رمز Token جديد) وكلما إنتهت هذه الفترة يتم إستخدام الـ refresh token للحصول على رمز جديد (بعض المواقع تقوم بإرسال رمز refresh token جديد أيضًا في هذه العملية، ولا يكون الرمز refresh token صالح للإستخدام مرة أخرى)، ويكون للـ refresh token فترة صلاحية أيضًا ولكن أكبر من رمز token العادي (قد تكون عدة أيام أو حتى أسابيع)، بعد إنتهاء هذه الفترة يجب على المستخدم أن يقوم بتسجيل الدخول مرة أخرى. ماذا سوف يحدث إذا قام المخترق بالوصول إلى كلٍ من رمز Token وكذلك Refresh Token؟ سوف يكون بإمكانه توليد رموز Token جديدة ويقوم بإستعمالها وكأنه المستخدم الحقيقي إلى أن تنتهي صلاحة الـ refresh token ويحتاج إلى تسجيل الدخول مرة أخرى. ملاحظة: إذا إستطاع أحد المخترقين الوصول إلى بيانات تسجيل الدخول الخاصة بالمستخدم (البريد الإلكتروني وكلمة السر) فسيكون بإمكانه توليد رموز token و refresh token كذلك إلى أن يقوم المستخدم بتغير كلمة السر الخاصة به. ملاحظة: الـ refresh token قد يتم تخزينه على الخادم، وعندما يقوم أحد المستخدمين بطلب رمز token جديد عبر الـ refresh token الخاص به، يقوم الخادم بالتحقق من أن الـ refresh token l موجود بالفعل لديه، وبالتالي يمكن التحكم في الـ refresh token وحذفه في حالة تم إستخدامه مرة واحدة أو قام المستخدم بتغير بياناته، أو قام بطلب رمز token من عنوان ip مختلف .. إلخ، مما يوفر أمان أكبر للـ refresh token من الإستخدام حتى بعد سرقته. يجب أن تعلم أيضًا أنه توجد دائمًا طريقة لإختراق أحد المستخدمين وإرسال بعض الطلبات على أساس أن المستخدم الحقيقي هو من طلبها، ويتوقف الأمر على العميل نفسه وفي عادات الحماية التي يتبعها مثل عدم تحميل ملفات من مواقع غير أمنة أو عدم إستخدام http لإرسال أي طلبات أو إستخدام كلمة سر مختلفة لكل موقع وتغيرها كل فترة من الزمن .. إلخ. ويمكن للموقع مساعدة المستخدمين في هذا الأمر من خلال إجبار المستخدم على إختيار كلمة سر قوية وإجباره على تغيرها كل فترة من الزمن وعدم إستقبال أي طلبات من نوع http تأتي إلى الخادم .. إلخ.
  16. هذه الخاصية تسمى autoescaping وهي موجودة بشكل إفتراضي لحماية الموقع من ثغرات مثل XSS ، ولكن تدعم قوالب jinja إيقاف هذه الخاصية في جزء معين من خلال إضافة المرشح safe| إلى اسم المعامل، على النحو التالي: {{ htmlcode|safe }} وإن كان لديك العديد من المتغيرات التي تريد عرضها فيمكنك أن تقوم بإيقاف الخاصية autoescaping في جزء من القالب على النحو التالي: {% autoescape false %} {{ something }} <p>{{ something_else }}</p> <b>{{ something_important }}</b> {% endautoescape %} الطريقة الأخرى هي إستخدام MarkupSafe، حيث توفر الدالة Markup التي تقوم بنفس مهمة المرشح safe| السابق، يمكنك تحميل المكتبة من خلال الأمر التالي: pip install -U MarkupSafe ثم يمكنك أن تستعملها على النحو التالي from markupsafe import Markup htmlcode = Markup('<p>HTML Content</p>') الآن يمكنك تمرير المتغير htmlcode إلى أي قالب وسوف يتم عرض محتواه بدون مشكلة وبدون إستعمال المرشح safe| ملاحظة: لا تقم بإستخدام هذه الطرق إلا إذا كنت متأكد من محتوى htmlcode السابق، وذلك لكي لا يتعرض الموقع لهجمات cross-site scripting (XSS)
  17. الدالة url_for تستقبل معاملات keywords حيث يمكنك أن تقوم بتمرير قيمة user_id مباشرة كمعامل للدالة url_for وسوف يتم توليد العنوان بالكامل: @app.route('/foo') def foo(): print(url_for('index', user_id = 123)) # /users/123 return "Foo Page" سوف يتم تعويض قيمة المتغير user_id في المسار بالقيمة 123، وإذا كان المتغير user_id إختياري فليس عليك أن تقوم بتمرير أي قيمة. يمكنك معرفة المزيد عن الدالة url_for من خلال هذه المقالة:
  18. يوفر فلاسك Flask إمكانية الوصول إلى http headers من خلال الكائن request حيث يحتوي على قاموس بإسم headers ويمكنك أنت تستخدمه للوصول إلى الترويسات headers: from flask import request @app.route('/') def index(): print(request.headers['authorization']) return "hello, world" ملاحظة: إذا لم يكن الـ authorization header موجود ضمن الترويسات المرسلة فسوف تحصل على خطأ KeyError، ولكي تتخطى هذا الخطأ يمكنك أن تستعمل التابع get للحصول على الترويسة وإذا لم يكن موجود سوف تحصل على None: from flask import request @app.route('/') def index(): print(request.headers.get('authorization')) return "hello, world" أو يمكنك التأكد من خلال إستخدام المعامل in في جملة شرطية كالتالي: from flask import request @app.route('/') def index(): if 'authorization' in request.headers: print(request.headers['authorization']) return "hello, world"
  19. يمكنك أن تستعمل التابع execute من الكائن engine، على النحو التالي: rows = db.engine.execute("SELECT * FROM userss") كما يمكنك تمرير بعض العوامل والقيم لتفادي ثغرة SQL Injection : result = db.session.execute('SELECT * FROM users WHERE age > :val', {'val': 18}) ويمكنك عمل commit في حالة أردت أن تقوم بتنفيذ جملة تعدل على قاعدة البيانات عليك أن تستخدم التابع execution_options: rows = db.engine.execute("<sql>").execution_options(autocommit=True)) أو يمكنك أن تقوم بإستخدام التابع text: from sqlalchemy import text sql = text('select name from users') result = db.engine.execute(sql) names = [row[0] for row in result] print(names) يمكنك الحصول على مزيد من المعلومات عن SQLAlchemy من خلال هذه المقالة:
  20. يوفر فلاسك Flask إمكانية معرفة عنوان IP الخاص بالمستخدم من خلال إستخدام الكائن request، حيث يحتوي على الخاصية remote_addr والتي تشير إلى عنوان IP الخاص بالمستخدم: from flask import Flask, request @app.route('/') def foo(): ip = request.remote_addr return f"your IP is {ip}" إذا قام أي مستخدم بزيارة المسار / سوف يحصل على عنوان IP الخاص به: your IP is 104.16.154.36 وإذا قمت بتشغيل التطبيق من خلال خادم محلي localhost أو إذا كنت تستعمل proxy لتشغيل التطبيق مثل إستخدام nginx سوف تحصل على النتيجة التالية: your IP is 127.0.0.1 لذلك يمكنك إستعمال الكود التالي للحصول على عنوان المستخدم نفسه حتى وإن كنت تستعمل proxy: from flask import Flask, request @app.route('/') def foo(): if request.environ.get('HTTP_X_FORWARDED_FOR') is None: ip = request.environ['REMOTE_ADDR'] else: ip = request.environ['HTTP_X_FORWARDED_FOR'] # if behind a proxy return f"your IP is {ip}"
  21. عند زيارتك لأي موقع على الإنترنت فأنت تستعمل منفذ معين (مثل 80 أو 443) وهذه هي المنافذ الإفتراضية لـ http و https ولذلك يقوم المتصفح بإخفاء هذا الجزء، فعلى سبيل المثال عندما تدخل إلى موقع أكاديمية حسوب فأنت تستعمل الرابط التالي: https://academy.hsoub.com ولكن يقوم المتصفح بإضافة منفذ 443 (لأن الموقع يستعمل https)، وبالتالي فيمكنك أن تدخل إلى أكاديمية حسوب عبر الرابط التالي أيضًا: https://academy.hsoub.com:443 وبالتالي فيمكنك أن تقوم بتغير المنفذ الخاص بمشروعك لكي يستخدم المنفذ 80 (أو 443 إذا كنت تستعمل شهادة SSL)، على النحو التالي: app.run(host='0.0.0.0', port=80) أو إذا كنت تستعمل الأمر flask: flask run --host=0.0.0.0 --port=80 بهذا الشكل يمكنك أن تقوم بتشغيل المشروع من خلال http://localhost مباشرة.
  22. يمكنك أن تستعمل التابع flask.redirect حيث يقوم هذا التابع بإستقبال الرابط الذي تريد توجيه المستخدم إليه كمعامل أساسي: from flask import Flask,redirect app = Flask(__name__) @app.route('/go') def go(): return redirect("http://www.google.com") كما يستقبل هذا التابع رقم الطلب (redirect status code) كمعامل ثاني باسم code: @app.route('/go') def go(): return redirect("http://www.google.com", code=302) يمكنك الإطلاع على هذه الإجابة هنا لمعرفة الفرق بين أرقام الحالة الخاصة بإعادة التوجية: ما إن أردت أن يتم إعادة توجيه المستخدم إلى مسار معين داخل الموقع، فيمكنك أن تستخدم التابع url_for للحصول على الرابط الكامل لمسار معين، ثم يمكنك أن تستعمل الرابط الذي تم إنشائه هذا في التابع redirect مرة أخرى: from flask import Flask, redirect, url_for @app.route('/go') def go(): return redirect(url_for('foo')) # سيتم توليد مسار localhost:5000/foo @app.route('/foo') def foo(): return 'Hello Foo!' كما يمكنك الإطلاع على هذه المقالة هنا والتي سوف تساعدك في إنشاء موقع لإختصار الروابط بإستخدام فلاسك Flask:
  23. يدعم فلاسك Flask هذا الأمر بشكل إفتراضي وبدون تثبيت أي حزم أو مكتبات خارجية، ولكن عليك أن تقوم ببعض الخطوات للقيام بهذا الأمر. تفعيل وضع التطوير في المشروع في البداية يجب أن تقوم بتفعيل وضع التطوير في المشروع Development Mode، ويكمنك أن تقوم بهذا الأمر بأكثر من طريقة: تمرير المعامل debug إلى التابع app.run: app.run(debug=True) تغير قيمة الخاصية app.debug إلى True: app.debug = True عمل متغير بيئة environment variable باسم FLASK_ENV وبقيمة development في سطر الأوامر: في ويندوز (CMD): SET FLASK_ENV=development في لينكس وماك: export FLASK_ENV=development تحديد ملف المشروع الرئيسي الآن عليك أن تقوم بعمل متغير بيئة ثاني يعبر عن ملف المشروع الرئيسي (في الغالب يكون main.py): في ويندوز (CMD): SET FLASK_APP=main.py في لينكس وماك: export FLASK_APP=main.py تشغيل المشروع في الغالب أنت تقوم بتشغيل تطبيق فلاسك Flask من خلال تشغيل ملف المشروع الرئيسي يدويًا، كالتالي: python main.py لكن للحصول على ميزة إعادة التحميل التلقائية عليك أن تستعمل الأمر flask لتشغيل المشروع، على النحو التالي: flask run الآن عند عمل أي تغير في ملفات المشروع وحفظ هذه الملفات ستجد أن المشروع يتم إعادة تشغيله بشكل تلقائي في سطر الأوامر دون تدخل منك. يمكنك أيضًا تغير منفذ المشروع الإفتراضي ليكون أي منفذ آخر من خلال تمرير المعامل port-- إلى الأمر السابق، كالتالي: flask run --port 8080 الآن سيعمل المشروع على الرابط localhost:8000
  24. يمكنك أن تقوم بعمل معاملات إخيارية عبر طريقتين: الطريقة الأولى من خلال إستخدام أكثر من مسار لنفس الدالة، ووضع قيمة إختيارية للمعامل page في الدالة: @app.route('/posts/') # يجب أن ينتهي المسار بعلامة / لكي يعمل بشكل سليم @app.route('/posts/<page>') def posts(page = 1): # القيمة الإفتراضية للمعامل page return str(page) الطريقة الثانية هي من خلال إستخدام المعامل defaults، حيث أن التابع app.route يقوم بإستقبال معامل إختياري باسم defaults لتحديد معاملات الدالة الإفتراضية، ونستخدمه في المسارات التي قد لا تحتوي على أحد (أو بعض) معاملات الدالة نفسها، على النحو التالي: @app.route('/posts/', defaults={'page': 1}) # يجب أن ينتهي المسار بعلامة / لكي يعمل بشكل سليم @app.route('/posts/<page>') def posts(page): return str(page) كلا الطريقتين السابقتين تقوم بنفس المهمة، ولكن يفضل إستخدام الطريقة الثانية لأنها لا تقوم بتعديل معاملات الدالة نفسها، مما يؤدي إلى تفادي بعض الأخطاء غير المقصودة.
  25. التابع flask.jsonify يعيد نتيجة من نوع flask.Response أي يكون كود JSON جاهز ليتم إرساله إلى العميل، ويتم إرسال ترويسة content-type بقيمة application/json حتى يتمكن العميل من معرفة نوع البيانات المرسلة إليه، ويقوم بمعالجتها بشكل سليم، على الجانب الآخر التابع json.dumps يقوم بتحويل قاموس Dictionary من البيانات (أو قائمة List) إلى نص ليتم إستخدامه أو إرساله أو تخزينه لوقت لاحق، وإذا إستخدمت هذا التابع في إرسال كود JSON إلى العميل فلن يتم تجهيز ترويسة من content-type بقيمة application/json، ولكن سيتم إستخدام القيمة الإفتراضية text/html; charset=utf-8 يمكنك أن تتأكد من الترويسات المرسلة إلى العميل من خلال أدوات مثل Postman أو أدوات المطورين Dev tool، كما في الصورة التالية: عند إستعمال التابع flask.jsonify عند إستعمال التابع json.dumps لاحظ أيضًا كيف تعرفت الإضافة JSON Formatter على كود JSON عند إستعمال التابع flask.jsonify، بينما لم تتعرف عليه عند إستعمال التابع json.dumps، وذلك بسبب الترويسة content-type لذلك إن أردت أن تقوم بعمل API أو تريد أن ترسل كود JSON بشكل عام، فعليك أن تستعمل التابع flask.jsonify المُعد لهذا الأمر، بينما إذا أردت أن تقوم بتخزين الكود في قاعدة بيانات أو ملف ما، فعليك أن تستعمل التابع json.dumps ملاحظة: التابع flask.jsonify يستخدم التابع json.dumps ضمنيًا لكي يقوم بتحويل القواميس والقوائم إلى نص String، ولكن يتم تجهيز الترويسة content-type كما ذكرت سابقًا.
×
×
  • أضف...