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

سامح أشرف

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

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

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

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

    56

إجابات الأسئلة

  1. إجابة سامح أشرف سؤال في كيفية برمجة Boot بوت للقيام بالبحث أو النشر بشكل تلقائي كانت الإجابة المقبولة   
    تحتاج إلى تعلم بعض الأدوات مثل لغة برمجة تستمح لك بالقيام بهذه الأمور، وفي الغالب يتم إستخدام لغة بايثون Python نظرًا لسهولتها وسرعة تعلمها، أيضًا تحتاج أن تتعلم بعض الأساسيات في التعامل مع الشبكة وكيفية إرسال طلبات requests من خلال لغة البرمجة، كيفية تحميل المواقع بإستخدام بايثون أو كيفية تحميل صورة معينة إلى الجهاز على سبيل المثال، وفي الغالب يتم إستعمال مكتبة requests للقيام بهذا الأمر حيث توفر سهولة كبيرة في التعامل مع هذه الطلبات.
    أيضًا يمكنك تعلم كيفية التحكم بالمتصفح من خلال لغة البرمجة، على سبيل المثال تجعل المتصفح يذهي إلى موقع جوجل ويكتب جملة معينة في مربع البحث ثم يضغظ على زر البحث ويطبع في سطر الأوامر النتائج التي حصل عليها من جوجل، ويمكن القيام بهذا الأمر بإستخدام مكتبة selenium وهي مشهورة للغاية في هذا المجال.
    ملاحظة: يسمى هذا المجال بمجال سحب البيانات من الإنترنت Web Scraping 
    أيضًا في كثير من الأحيان ستضطر إلى البحث عن واجهة برمجية API خاصة بالتطبيق أو الموقع الذي تريد القيام فيه ببعض الأمور، فعلى سبيل المثال إن أردت أن تقوم ببرمجة بووت للنشر على أحد المجموعات في تليجرام Telegram فعليك أن تقرأ توثيق Telegram APIs الذي يشرح لك كيفية عمل برامج تستخدم التطبيق وتقوم بالنشر فيه أو القيام بأمور أخرى مختلفة.
    في دورة علوم الحاسوب يتم شرح كل الأساسيات التي تحتاجها للبدء في تعلم هذه الأمور، حيث يتم شرح لغة بايثون من الصفر وكذلك البرمجة الكائنية والخوارزميات وهياكل البيانات وغيرها من الأمور وكذلك يتم شرح ما هي الطلبات requests وكيف يقوم المتصفح بإرسال الطلبات إلى الخوادم servers ليحصل على رد response (في الغالب يكون كود HTML)، لذلك ستكون هذه الدورة مفيدة لك للغاية قبل تعلم الأمور المذكورة أعلاة.
  2. إجابة سامح أشرف سؤال في كيفية سحب الصور من تصميم figma كانت الإجابة المقبولة   
    إذا كان لديك صور في تصميم في Figma فيمكنك أن تقوم بإستخراجها من خلال تحديدها أولًا ثم ستجد قائمة Export في أسفل اليمين كما في الصورة التالية، قم بالضغط على علامة + ثم أختر حجم وصيغة الصورة وفي النهاية أضغط على Export وستجد أن الصورة تم تنزيلها لديك:

    يمكنك أيضًا أن تقوم بإستخراج أكثر من صورة في نفس الوقت من خلال تحديد الصور والقيام بنفس الخطوات والضغط على Export Layers وسيتم تحميل ملف مضغوط يحتوي على كل الصور المُحددة سابقًا:

  3. إجابة سامح أشرف سؤال في لقد تعطلت الواي فاي في اللابتوب كانت الإجابة المقبولة   
    قم بالضغط على زر الواي فاي الموجود في أسفل يمين الصورة لديك ليتم تشغيل الواي فاي مرة أخرى.
    إن لم يعمل، قم بفتح الإعداداا Settings ثم قسم الشبكة والإنترنت Network & Internet ومن القائمة الجانبية إختر Wifi ثم قم بتفعيل الواي فاي، كما في الصورة:

    أيضًا قد يكون لديك زر في الحاسوب الخاص بك مخصص لإغلاق الواي فاي وتشغيله وعليك أن تقوم بالضغط عليه، لاحظ الزر في الصورة التالية:

  4. إجابة سامح أشرف سؤال في كيف أرفع عدة صور في express.js؟ كانت الإجابة المقبولة   
    يجب تعديل كود HTML ليتم السماح برفع أكثر من ملف بالشكل التالي:
    <input name="avatar" type="file" multiple /> أيضًا يجب تعديل كود Multer ليقوم بإستقبال أكثر من ملف بالشكل التالي:
    app.post('/add-product', upload.array('avatar', 12), function (req, res, next) { // req.files is array of `avatar` files // req.body will contain the text fields, if there were any }) ملاحظة يصبح الكائن الذي يحتوي على معلومات الصور باسم req.files وليس req.file وذلك لأنه يمكن أن يحتوي الآن على أكثر من صورة.
    وفي حالة أردت أن ترفع الصور من خلال أكثر من حقل فيمكنك أن تستعمل upload.feilds على النحو التالي:
    const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }]) app.post('/add-product', cpUpload, function (req, res, next) { // يمكن الوصول إلى معلومات الصور بالشكل التالي // req.files['avatar'][0] -> File // req.files['gallery'] -> Array مصفوفة من الصور }) الأمر الأخير هو أنه يجب تعديل الـ Schema في النموذج model ليتم تخزين مصفوفة من النصوص array of string بدلًا من نص واحد string:
    const productSchema = new Schema({ avatar: [{ type: String }] }); ملاحظة: قد ترغب في تغير اسم الحقل ليكون avatars أو شيء آخر يعبر عن وجود أكثر من صورة بدلًا من avatar فقط.
    ملاحظة: يرجى إضافة الشيفرات بمحرر الشيفرات وليس كصور
  5. إجابة سامح أشرف سؤال في كيفية معرفة إصدار فلاسك Flask المثبت حاليًا؟ كانت الإجابة المقبولة   
    بداية من الإصدار 0.7 في فلاسك Flask تم إضافة الخاصية __version__ والتي تحتوي على رقم الإصدار الحالي (المثبت لديك):
    >>> import flask >>> flask.__version__ '1.1.2' >>> إن كنت تعمل على إصدار أقدم من 0.7 فسوف يسبب الكود السابق خطأ AttributeError لأن الخاصية لم تكن موجودة بعد حينها، لكن يمكنك أن تقوم بإستخدام المكتبية pkg_resources لمعرفة إصدار فلاسك Flask لديك:
    >>> import pkg_resources >>> pkg_resources.get_distribution('flask').version '0.6.1' ملاحظة: الطريقة السابقة تعمل مع كل الإصدارات ولكن قد تحتاج إلى تنفيذ الأمر التالي إن لم تجد المكتبة pkg_resources لديك:
    pip install setuptools طريقة أخرى وهي إستخدام الامر freeze والذي يقوم بعرض كل المكتبات المثبتة لديك وإصداراتها:
    pip freeze وإن كنت تستعمل ليتنكس فيمكنك أن تعرض إصدار مكتبة فلاسك Flask فقط بهذا الشكل:
    pip freeze | grep flask أيضًا تستطيع أن تستخدم الأمر flask (إن كان يعمل لديك) وسيعرض لك إصدار بايثون وفلاسك وكذلك Werkzeug:
    flask --version
  6. إجابة سامح أشرف سؤال في فلاسك Flask لا يتعرف على التغيرات في ملفات js. كانت الإجابة المقبولة   
    قد يكون سبب هذه المشكلة هو المتصفح نفسه وليس فلاسك Flask وللتأكد من هذا الأمر حاول أن تقوم بتجربة المشروع بإستخدام متصفح مختلف فإذا تم تحميل الملفات بشكل صحيح وتحتوي على آخر التحديثات، فيجب أن تقوم بحذف الملفات المؤقتة من متصفح الويب الخاص بك من خلال أحد هذه الطرق (تختلف حسب نظام التشغيل لديك):
    ويندوز: Ctrl+F5
    ماك: Cmd+Shift+R أو Cmd+Opt+R 
    لينكس: Ctrl+Shift+R
    أيضًا تستطيع تغير اسم ملف JavaScript وسيقوم المتصفح بإعادة تحميله مرة أخرى بأحدث التعديلات عليه.
    يمكنك أيضًا أن تضيف متغير إلى رابط الملف كمعامل URL بالشكل التالي:
    script.js?some_variable=file_timestamp حيث تقوم بتغير قيمة المعامل file_timestamp بإستخدام فلاسك Flask في القالب بأي رقم عشوائي Random وحينها سيقوم المتصفح بإعادة تحميل الملف كل مرة، على النحو التالي:
     
    def last_updated_timestamp(folder): return str(max(os.path.getmtime(os.path.join(root_path, f)) for root_path, dirs, files in os.walk(folder) for f in files)) @app.route('/') def index(): return render_template('index.html', timestamp=last_updated_timestamp('./static')) # في القالب <script type="text/javascript" src="/static/script.js?u={{ timestamp }}"></script> وستكون النتيحة بالشكل التالي:
    <script type="text/javascript" src="/static/script.js?u=1641149029.12"></script> حل آخر وهو إخبار المتصفح بألا يقوم بحفظ الملفات لأكثر من فترة معينة من خلال تحديد الخاصية cache_control.max_age بعدد ثواني معينة بالشكل التالي:
    @app.route('/api/v1/users/') def get_users(): data = {"name": "sameh"} response = jsonify(data) response.cache_control.max_age = 60 * 60 * 24 # يوم واحد بالثواني return response بهذا الشكل لن يقوم المتصفح بحفظ الملفات الثابتة (ملفات CSS/JS/JSON .. إلخ) لفترة أطول من يوم واحد.
  7. إجابة سامح أشرف سؤال في تشغيل دالة في الخلفية بعد إرسال رد response في فلاسك Flask؟ كانت الإجابة المقبولة   
    لتشغيل دالة في الخلفية (في thread مختلفة) تحتاج إلى إستعمال المكتبة threading بالشكل التالي:
    import time import threading from flask import Flask app = Flask(__name__) @app.route('/start') def start_handler(): # هذه الدالة ستعمل في الخلفية للقيام ببعض المهام def handle_sub_work(): for i in range(20): print(i, time.time()) time.sleep(1) # تشغيل Thread جديد threading.Thread(target=handle_sub_work).start() return "started" app.run(debug=True) بهذا الشكل سوف تعمل الدالة handle_sub_work في خيط Thread جديد، ولن يحتاج العميل الإنتظار لكي تنتهي هذه الدالة من العمل حتى يحصل على الطلب.
    ملاحظة: الدالة handle_sub_work تعمل في Thread جديد لذلك ليس لديها أي وصول إلى الكائن request الحالي، ولكن يمكن حل هذه المشكلة من خلال copy_current_request_context بالشكل التالي:
    @app.route('/start') def start_handler(): @copy_current_request_context def handle_sub_work(): for i in range(20): print(i, time.time()) print(request.url) # لتتأكد من إمكانية الوصول إلى الكائن request الحالي time.sleep(1) threading.Thread(target=handle_sub_work).start() return "started"  
  8. إجابة سامح أشرف سؤال في مشكلة رفض الطلب connection refused في فلاسك Flask؟ كانت الإجابة المقبولة   
    يجب تشغيل التطبيق وتحديد أن عنوان المضيف host بعنوان 0.0.0.0 على النحو التالي:
    if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) بهذا الشكل يمكنك أن تقوم بتشغيل المشروع على الشبكة المحلية، فعلى سبيل المثال إن كان الجهاز لديه العنوان:
    192.168.X.X فيمكنك تشغيل المشروع http://192.168.X.X:5000
    كما يمكنك تشغيل المشروع من خلال الأمر flask:
    flask run --host=0.0.0.0 --port=5000 كما إن كنت تستخدم جدار ناري firewall للحماية فعليك أن تسمح بتشغيل المنفذ 5000 من خلال الأمر التالي: sudo ufw allow 5000  
  9. إجابة سامح أشرف سؤال في إضافة صنف CSS في نماذج wtform في فلاسك Flask؟ كانت الإجابة المقبولة   
    يمكن إضافة الخاصية _class (لاحظ علامة _ في نهاية الكلمة لأن الكلمة class محجوزة في بايثون)
    {{ form.email(class_="css-class-here") }} وستكون النتيجة بهذا الشكل:
    <input class="css-class-here" id="email" name="email" type="text" value=""> كما يمكنك أن تقوم بإضافة أي خاصية HTML إلى الحقل من خلال تمرير كائن إلى المعامل render_kw بالشكل التالي:
    email = EmailField('Email', render_kw={'class': 'css-class-here', 'style': 'background:red;'}) <input class="css-class-here" id="email" name="email" type="text" value="" style="background:red;">  
  10. إجابة سامح أشرف سؤال في تمرير بيانات عند إعادة التحويل redirect في فلاسك Flask؟ كانت الإجابة المقبولة   
    تستطيع أن تقوم بتمرير الرسائل بإستخدام معاملات عنوان URL (تسمى URL parameter) بالشكل التالي:
    from flask import session, url_for def foo(): messages = json.dumps({"title":"hello world"}) # تحويل الكائن إلى نص return redirect(url_for('hello', messages=messages)) @app.route('/hello') def hello(): messages = request.args['messages'] # لإستعادة الرسائل من الدالة url_for() return render_template("hello.html", messages=json.loads(messages)) أو يمكنك أن تستعمل الجلسة session لتخزين قيمة message في cookie ثم إستخراج قيمة message من داخل هذه الـ cookie في الدالة hello بالشكل التالي:
    from flask import session, url_for def foo(): messages = json.dumps({"title":"hello world"}) # تحويل الكائن إلى نص session['messages'] = messages # تخزينه في الـ session return redirect(url_for('hello')) @app.route('/hello') def hello(): messages = session['messages'] # لإستعادة الرسائل من الـ session return render_template("hello.html", messages=json.loads(messages))
  11. إجابة سامح أشرف سؤال في كيفية عرض رقم float بعدد خانات معين في قالب Jinja في فلاسك Flask؟ كانت الإجابة المقبولة   
    يمكنك أن تقوم بعرض أي رقم float بخانتين فقط بعد العلامة العشرية من خلال إستعمال الدالة format، بالشكل التالي:
    {{'%0.2f'| format(result|float)}}% أو من خلال إستخدام علامة % كما في الكود التالي:
    {{'%0.2f' % result|float}}% أيضًا تستطيع إستعمال المُرشح round لتقريب الرقم بالشكل التالي:
    {{ result|round }} وتستطيع تحديد كيف ستتم عملية التقريب من خلال تمرير معاملات إلى المرشح round بالشكل التالي:
    {{ result|round(1, 'common', ) }} المعامل الأول هو مقدار الدقة precision وقيمته الإفتراضية هي 0، بينما المعامل الثاني هو كيف ستتم عملية التقريب "ceil" (التقريب إلى الرقم الأعلى) أم "floor" (التقريب إلى الرقم الأقل) أم "common" (التقريب الرياضي العادي).
  12. إجابة سامح أشرف سؤال في كيفية التحقق من عدد نتائج sqlalchemy في فلاسك Flask؟ كانت الإجابة المقبولة   
    تستطيع إستخدام التابع query.one والذي يقوم بإرجاع نتيجة واحدة فقط، وفي حالة وجود أكثر من نتيجة سوف يقوم برفع استثناء MultipleResultsFound أما إذا لم يتم العثور على أي نتائج فسوف يقوم برفع استثناء NoResultFound، ويمكن تطبيق هذه الفكرة من خلال جملة Try .. except، على النحو التالي:
    from sqlalchemy.orm.exc import NoResultFound from sqlalchemy.orm.exc import MultipleResultsFound try: user = session.query(User).one() return jsonify(result) except MultipleResultsFound, e: return "more than one" except NoResultFound, e: return "no results found" بهذا الشكل يمكنك تنفيذ ما تريد عندما يوجد نتيجة واحدة فقط أو يوجد عدد أكبر من النتائج أو لا يوجد نتائج على الإطلاق.
  13. إجابة سامح أشرف سؤال في كيفية الحصول على اسم الدالة الحالية في فلاسك Flask؟ كانت الإجابة المقبولة   
    يوفر فلاسك Flask الخاصية endpoint في الكائن request وهي مسئولة عن حفظ اسم الدالة التي يتم تنفيذها عند زيارة المسار، انظر الكود التالي:
    from flask import Flask, request app = Flask(__name__) @app.route("/") def foo(): return request.endpoint # foo app.run(debug=True) عند زيارة المسار / سوف يتم إرجاع اسم الدالة "foo".
    يمكنك أيضًا أن تقوم بإستخدام المكتبة inspect للحصول على اسم الدالة الحالية، على النحو التالي:
    import inspect @app.route("/") def foo2(): return inspect.currentframe().f_code.co_name عند زيارة المسار / سوف يتم إرجاع اسم الدالة "foo2".
  14. إجابة سامح أشرف سؤال في كيفية الحصول على أول صف row عبر sqlalchemy في فلاسك Flask؟ كانت الإجابة المقبولة   
    إستخدم التابع Query.first للحصول على صف واحد فقط وليس مجموعة من الصفوف بالشكل التالي:
    users = session.query(user.name).filter(and_(user.email == email, user.password == password_hash)).one() وتستطيع أيضًا أن تستعمل التابع Query.one_or_none والذي يقوم بإرجاع نتيجة واحدة فقط أو None في حالة لم يتم العثور على نتيجة مطابقة في قاعدة البيانات:
    users = session.query(user.name).filter(and_(user.email == email, user.password == password_hash)).one_or_none()
  15. إجابة سامح أشرف سؤال في كيفية معرفة المسار route الحالي في فلاسك Flask؟ كانت الإجابة المقبولة   
    يوفر فلاسك Flask إمكانية الوصول إلى المسار الحالي من خلال إستخدام الكائن request، حيث يحتوي على الخاصية path التي تحمل المسار الحالي:
    from flask import Flask, request @app.route("/users/") @app.route("/show-users/") def show_users(): return request.path في الكود السابق سوف يتم عرض المسار المستخدم للوصول إلى الدالة show_users 
    أيضًا يمكنك أن تستعمل url_rule بطريقة مشابهة، على النحو التالي:
    from flask import Flask, request @app.route("/users/") @app.route("/show-users/") def show_users(): return str(request.url_rule) وسوف يؤدي هذا الكود نفس الغرض.
  16. إجابة سامح أشرف سؤال في تعريف متغير واستخدامه داخل وظيفة أخرى بواسطة جافا سكريبت كانت الإجابة المقبولة   
    لكي يتم إضافة التدوينات في الأقسام المحددة، تحتاج إلى تعديل الدالة lastPosts و الدالة createLastPosts وكذلك تحتاج إلى إنشاء مصفوفة عامة global بالشكل التالي:
    var IDs = []; function lastPosts(json) { var ID = IDs.shift(); // للحصول على أول عنصر في المصفوفة وحذفه من المصفوفة الأصلية // ... var printall = document.getElementById(ID); printall.innerHTML += printArticle; } function createLastPosts(url, count, printId) { IDs.push(printId); // لإضافة عنصر جديد إلى المصفوفة // ... } الآن يمكنك أن تقوم بتشغيل الدالة createLastPosts أكثر من مرة وسوف يتم إضافة التدوينات في الأماكن المحددة:
    <div class="container"> <div class="wrapper"> <div class="content"> <div id="demo1" class="show-sidebar grid grid-3"></div> <div id="demo2" class="show-sidebar grid grid-3"></div> <div id="demo3" class="show-sidebar grid grid-3"></div> </div> </div> </div> <script> createLastPosts('https://mo-222.blogspot.com', '1', 'demo1'); createLastPosts('https://mo-222.blogspot.com', '2', 'demo2'); createLastPosts('https://mo-222.blogspot.com', '3', 'demo3'); </script>
    طريقة أفضل
    لكن الطريقة السابقة متوقفة على ترتيب تنفيذ السكريبتات في المتصفح ولا يمكننا أن نضمن أن يتم تنفيذهم بالترتيب (قد يقوم المتصفح بتنفيذ السكريبتات حسب سرعة تحميل كل سكريبت) وبالتالي يمكن أن نجد أن التدوينات يتم إضافتها في أماكن عشوائية، ولحل هذه المشكلة يمكن أن تقوم بتجربة طريقة مختلفة عن إستخدام مصفوفة عامة، حيث نقوم بإضافة خاصية باسم data-position في كل عنصر script وتحمل id الخاص بالعنصر  الذي سيتم إضافة التدوينات فيه، بالشكل التالي:
    function lastPosts(json) {     // للحصول على الخاصية data-position من السكريبت الحالي (الذي قام بإستدعاء هذه الدالة)     var ID = document.currentScript.getAttribute('data-position')     //  ...         var printall = document.getElementById(ID);         printall.innerHTML += printArticle;     } } function createLastPosts(url, count, printId) {     // ... ثم يتم إستدعاء الدالة createLastPosts بنفس الطريقة:
    <div class="container"> <div class="wrapper"> <div class="content"> <div id="demo1" class="show-sidebar grid grid-3"></div> <div id="demo2" class="show-sidebar grid grid-3"></div> <div id="demo3" class="show-sidebar grid grid-3"></div> </div> </div> </div> <script> createLastPosts('https://mo-222.blogspot.com', '1', 'demo1'); createLastPosts('https://mo-222.blogspot.com', '2', 'demo2'); createLastPosts('https://mo-222.blogspot.com', '3', 'demo3'); </script> الملف بعد تعديله: 
    last-post.html
  17. إجابة سامح أشرف سؤال في كيفية إستخدام ملفات React مع فلاسك Flask؟ كانت الإجابة المقبولة   
    عندما تقوم بإستضافة تطبيقات ذات الصفحة الواحدة Single Page Application (SPA) فسيتم إدارة أغلب المسارات من خلال كود الواجهة الأمامية عبر JavaScript (لكي لا يتم إعادة تحميل الصفحة من الخادم) وبالتالي يجب أن يقوم الخادم بإرسال ملف index.html عند زيارة أي مسار (حتى إن لم يوجد هذا المسار في تطبيق فلاسك Flask) وذلك من خلال الكود التالي:
    from flask import Flask, send_from_directory import os # يجب تحديد المجلد الصحيح الذي يحتوي على ملفات الواجهة الأمامية هنا app = Flask(__name__, static_folder='client/build') @app.route('/', defaults={'path': ''}) @app.route('/<path:path>') def serve(path): if path != "" and os.path.exists(app.static_folder + '/' + path): return send_from_directory(app.static_folder, path) else: return send_from_directory(app.static_folder, 'index.html') if __name__ == '__main__': app.run() بهذا الشكل سوف يتم إرجاع الملف index.html في كل المسارات غير المحددة بالفعل في التطبيق، أي أن أي مسار آخر موجود في فلاسك Flask سوف يعمل بدون مشكلة.
  18. إجابة سامح أشرف سؤال في خطأ No application found في فلاسك Flask؟ كانت الإجابة المقبولة   
    عندما تحاول الوصول إلى التطبيق الحالي current_app أو أي شيء يستعمله سوف تحصل على رسالة الخطأ التالية:
    RuntimeError: Working outside of application context. وهي مشابهة لرسالة الخطأ التي لديك، حيث أنك تحتاج إلى إستخدام app_context لعمل Push للـ context الخاص بالتطبيق بالشكل التالي:
    # في ملف app.py app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'My connection string' db.init_app(app) # لاحظ كيفية إستخدام الجملة with لتمرير app_context with app.app_context(): db.create_all() يمكنك أيضًا أن تقوم بإستخدام التابع push مباشرة (في حالة كنت تستعمل سطر الأوامر)، كالتالي:
    from flask import Flask from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() def create_app(): app = Flask(__name__) db.init_app(app) return app في سطر الأوامر:
    >>> from yourapp import create_app >>> app = create_app() >>> app.app_context().push() الطريقة الأخرى هي تمرير app نفسه إلى db.create_all:
    db.create_all(app=create_app())  
  19. إجابة سامح أشرف سؤال في كيفية إستخدام url_for للحصول على عنوان URL كامل في فلاسك Flask؟ كانت الإجابة المقبولة   
    الدالة url_for تقبل معامل آخر هو _external وإذا قمت بتمرير هذا المعامل بقيمة True سوف يتم إنتاج عنوان URL المطلق Absolute وليس عنوان نسبي Relative:
    url_for('index', _external=True) وقد تحتاج أن تحدد النطاق الذي سيتم إستخدامه من خلال تعين قيمة SERVER_NAME وكذلك البروتوكول المستخدم في إعدادات التطبيق، كالتالي:
    app.config['SERVER_NAME'] = "localhost:5000" app.config['PREFERRED_URL_SCHEME'] = "http" بهذا الشكل سوف يتم إنتاج عنوان URL كامل عند إستعمال الدالة url_for أيضًا
  20. إجابة سامح أشرف سؤال في خطأ Install 'email_validator' for email validation support عند تشغيل تطبيق فلاسك Flask؟ كانت الإجابة المقبولة   
    سبب هذا الخطأ أنك قمت بتثبيت WTForms بإصدار 2.3.1 أو أعلى ولكن لم تقم بتثبيت email_validator ويمكنك أن تقوم بتثبيت هذه الحزمة من خلال أحد الطرق التالية:
    عبر pip:
    pip install email-validator أو من خلال الأمر التالي:
    pip install wtforms[email] أو يمكنك أن تقوم بتثبيت إصدار أقدم من WTForms كالتالي:
    pip install wtforms==2.2.1  
  21. إجابة سامح أشرف سؤال في خطأ SQLite objects can only be used in same thread في فلاسك Flask؟ كانت الإجابة المقبولة   
    يمكن حل هذه المشكلة بأكثر من طريقة على النحو التالي:
    الطريقة الأولى هي فتح إتصال بقاعدة البيانات مع تمرير المعامل check_same_thread بقيمة Flase لكي لا يظهر هذا الخطأ على الإطلاق، وهذه هي الطريقة الأسهل، لأنك لن تضطر إلى التعديل على الكود إلا في مكان واحد، كالتالي:
    conn = sqlite3.connect('database-name.db', check_same_thread=False) الطريقة الأخرى هي فتح إتصال بقاعدة البيانات داخل الدالة register نفسها بإستخدام الجملة with لكي يتم غلق الإتصال تلقائيًا بمجرد الإنتهاء منه:
    @app.route('/api/v1/register', methods=['POST']) def register(): # باقي كود الدالة هنا with sql.connect("database-name.db") as conn: name = "bob" cur = conn.cursor() cur.execute("INSERT INTO users(name,email,username,password) VALUES(?,?,?,?)", [name, email, username, password]) conn.commit() return "Successful" بهذا الشكل سوف يعمل كود SQLite بدون مشكلة.
  22. إجابة سامح أشرف سؤال في كيفية إرجاع صورة مخزنة في قاعدة البيانات في فلاسك Flask؟ كانت الإجابة المقبولة   
    يمكنك حل هذه المشكلة من خلال إنشاء كائن Response (عبر الدالة make_response) وتحديد الترويسة Content-Type لتكون من نوع الصورة مثل image/jpeg ، وإن أردت أن يتم تحميل الصورة وحفظها بدلًا من عرضها على الشاشة فيجب أن تقوم بتحديد التوريسة Content-Disposition لتحمل القيمة attachment، على النحو التالي:
    @app.route('/images/<image_id>.jpg') def load_image(image_id): image_binary = read_image(image_id) # يتم هنا جلب الصور في شكل bson.Binary response = make_response(image_binary) response.headers.set('Content-Type', 'image/jpeg') # لتحميل الصورة وحفظها بدلًا من عرضها response.headers.set('Content-Disposition', 'attachment', filename='%s.jpg' % image_id) return response يمكنك أيضًا أن تستعمل الدالة send_file لإرسال كائن من نوع io.BytesIO:
    from flask import Flask, send_file @app.route("/images/<image_id>.jpg") def load_image(image_id): image_binary = read_image(image_id) # يتم هنا جلب الصور في شكل bson.Binary return send_file( io.BytesIO(image_binary), mimetype='image/jpeg', as_attachment=True, attachment_filename='%s.jpg' % image_id ) تستطيع أيضًا حفظ الصورة في ملف مؤقت على الخادم وإرسال هذا الملف بشكل عادي، والتحقق من وجود الملف أولًا لكي لا يتم إعادة حفظ نفس الصورة في كل مرة يتم طلبها.
  23. إجابة سامح أشرف سؤال في كيفية الحصول على SECRET_KEY بشكل آمن في فلاسك Flask؟ كانت الإجابة المقبولة   
    يمكنك أن تقوم بتوليد secret key بأكثر من طريقة في Python:
    بإستخدام مكتبة os (لبايثون 3): >>> import os >>> os.urandom(12).hex() 'f3cfe9ed8fae309f02079dbf'  
    بإستخدام مكتبة uuid (لبايثون 2 و 3): >>> import uuid >>> uuid.uuid4().hex '93ec461e09494cc782777a2d72849347' بإستخدام مكتبة secrets (لبايثون 3.6 أو أعلى): >>> import secrets >>> secrets.token_urlsafe(16) 'ZUhfGOVy7hC8Zvljx73jkQ' >>> secrets.token_hex(16) 'be193b8219c908baa36c17a64b58d39d' ويمكنك أن تضيف المفتاح بإستخدام أحد الطرق التالية:
    app.secret_key = 'the random string' app.config['SECRET_KEY'] = 'the random string' أو تضيف المفتاح إلى ملف الإعدادات، بالشكل التالي:
    SECRET_KEY = 'the random string'  
  24. إجابة سامح أشرف سؤال في كيف يمكن التحكم في وقت الجلسة session في فلاسك Flask؟ كانت الإجابة المقبولة   
    بشكل إفتراضي جلسات فلاسك Flask Session يتم إنهائها بمجرد إغلاق المتصفح، إلا في حالة واحدة وهو جعل الجسلة دائمة permanent session وتحديد وقت معين لإنتائها كالتالي:
    from datetime import timedelta from flask import session, app @app.before_request def make_session_permanent(): session.permanent = True app.permanent_session_lifetime = timedelta(minutes=15) بهذا الشكل سوف تستمر الجلسة حتى وإن قام المستخدم بإعادة تشغيل المتصفح الخاص به، وسوف تنتهي الجلسة بعد مرور 15 دقيقة من وقت تسجيل الدخول.
    ملاحظة: إن لم يتم تحديد مدة حياة الجلسة permanent_session_lifetime  فسوف تستمر لشهر كامل، بالتحديد لـ 31 يوم.
  25. إجابة سامح أشرف سؤال في كيفية إستدعاء ملفات HTML داخل Jinja في فلاسك Flask؟ كانت الإجابة المقبولة   
    يمكنك القيام بهذا الأمر من خلال تعليمة include في قوالب Jinja على النحو التالي:
    الملف index.html
    <!DOCTYPE html> <html lang="en"> <body> <h1>Index Content</h1> {% include 'footer.html' %} </body> </html> محتوى الملف footer.html:
    <h1>{{ name }}</h1> طريقة عرض الملف index.html:
    def index(): return render_template('index.html', name="sameh") # لاحظ تم تمرير المعامل name لأن الملف footer.html يحتاجه بهذا الشكل سوف يتم جلب محتوى الملف footer.html إلى داخل الملف index.html، أي تم إستدعائه، وستكون النتيجة في النهاية كالتالي:
    <!DOCTYPE html> <html lang="en"> <body> <h1>Content</h1> <h1>sameh</h1> </body> </html> ملاحظة: كل المتغيرات والبيانات الممررة إلى الملف index.html سوف يتم تمريرها إلى الملف footer.html أيضًا، لذلك عليك تمرير كل المتغيرات التي يحتاجها الملف footer.html إلى الملف index.html عند إستخدام الدالة render_template
×
×
  • أضف...