مُقدّمة:
بعد أن أعددنا السّند الخلفي لتطبيقنا، حان الوقت لإعداد النّظام الأمامي لتحسين تجربة الاستخدام، سنقوم في هذا الدّرس بإنشاء ملفّ HTML ليحتوي على حقل يُمكن المُستخدم من لصق الرّابط إليه، وسنستخدم لغة جافاسكربت لإرسال الرّابط إلى تطبيق Flask واستقبال الرّابط المُختصر، بعدها سنقوم بطرح الرّابط المُختصر مع إمكانيّة نسخه عن طريق الضّغط على زر واحد.
مُتطلّبات هذا الجزء
لتتمكّن من فهم هذا الدّرس بشكل كامل، ستحتاج إلى معرفة جيدة بلغة جافاسكربت وخاصّة تقنيّة Ajax وكيفيّة إرسال واستقبال طلبات HTTP باستعمال خاصيّة XMLHttpRequest، ومن المُفضّل إلقاء نظرة على الموضوع قبل إكمال قراءة هذا الدّرس، ويُمكنك أن تتعلّم اللغة هنا على موقع الأكاديميّة.
وتجدر الإشارة إلى أنّك ستحتاج إلى معرفة بسيطة بأداة git لتتمكّن من التّعامل مع منصّة Heroku لخدمات الاستضافة السّحابيّة.
الهدف من هذا الجزء
التّطبيق حاليا يعمل بشكل جيّد، يُمكنك زيارة رابط والحصول على المُعرّف الخاص وإضافته كلاحق لاسم النّطاق، وهكذا ستحصل على رابط مُختصر، صحيح بأنّ التّطبيق يختصر الرّوابط لكنّ طريقة العمل ليست ملائمة للمُستخدم العادي، ما سنقوم به في هذا الجزء هو تنسيق وإعداد ما يراه المُستخدم لجعل اختصار الرّوابط أكثر سهولة، ويُمكنك الاطّلاع على التّطبيق كاملا عبر هذا الرّابط
إعداد ملفّ HTML
سنقوم باستخدام ملف HTML واحد باسم index.html
بداخل مُجلّد templates
وسنربطه بملفّ جافاسكريبت باسم index.js
وملفّ css باسم style.css
اللذان سيكونان بداخل مجلّد static
.
ما يعني بأنّ الملفّات والمجلّدات ستكون كالتالي:
├── app.db ├── app.py ├── create_db.py ├── static │ ├── css │ │ └── style.css │ └── js │ └── index.js └── templates └── index.html
لتقديم ملفّ HTML سنقوم بتعديل الموجّه الرّئيسيّ ليُصبح كالآتي:
@app.route('/') def index(): return render_template("index.html")
بعدها سنُضيف الشيفرة التّالية إلى ملفّ index.html
:
<!DOCTYPE html> <html > <head> <meta charset="UTF-8"> <title>قصّرتك</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> </head> <body> <header> <h1>قصّرتُك</h1> <h3> خدمة تقصير الروابط الأكثر بساطة </h3> </header> <div id='bg-box'> <input name="link" type='text' id='input' placeholder='ضع رابطك هنا لتقصيره' onchange='change()'> <input type='text' id='result' value='الرّابط المُختصر هنا'> <a id='cp' href='#' onclick='copy()'>انسخ</a> <span id='msg' href='#'></span> </div> <script src="{{ url_for("static", filename="js/index.js") }}" > </script> </body> </html>
لاحظ بأنّنا جلبنا ملف style.css
في أعلى الملف وindex.js
في أسفله.
ستحتوي الصّفحة على حقل ليضع فيه المُستخدم رابطه (سمّيناه link
)، وحقل لعرض النّتيجة (أي الرّابط المُختصر)، ثم أضفنا رابطا ليعمل كزر لنسخ الرّابط المُختصر وكذلك وضعنا وسم span
لنعرض عليه رسالة النّجاح (أو الإخفاق) في نسخ الرّابط.
لاحظ كذلك بأنّنا نستدعي دالتين من ملفّ جافاسكربت هما change()
و copy()
مُباشرة بعد حدثي onchange
و onclick
على التّوالي. الأولى مسؤولة عن إرسال طلب لاختصار الرّابِط والأخرى لتمكين المُستخدم من نسخ الرّابط المُختصر.
إرسال واستقبال الطّلبات من وإلى تطبيق Flask بالاستعانة بلغة جافاسكريبت
سنستعمل تقنيّة AJAX لإرسال طلب اختصار الرّابط إلى تطبيق Flask فور استقباله من المُستخدم عبر حقل input
الأول المتواجد في الصّفحة الرّئيسيّة وعند استقبال الإجابة (والتي ستكون عبارة عن مُعرّف الرّابط في قاعدة البيانات مُشفّرا)، سنتعمد على تقنيّة DOM لتعديل مُحتويات الصّفحة وعرض النّتيجة إلى المُستخدم.
مُحتوى ملفّ جافاسكربت سيكون كالآتي:
function request(url,b,method,data,c){ request = new XMLHttpRequest; request.open(method||'get',url); request.onload=b; request.send(data||null) result = document.getElementById("result"); result.value = 'انتظر رجاء...' } function callback(e){ short_link = document.getElementById("result"); short_link.value = window.location.host + this.response } function change() { url = document.getElementById("input").value; request('shorten?link=' + url, callback, 'get') } // الدّالة المسؤولة عن نسخ الرّابِط المُختصر إلى لوحة مفاتيح المُستخدم function copy() { result = document.getElementById("result"); msg = document.getElementById("msg"); result.select(); try { var copy = document.execCommand('copy'); if(copy) msg.innerHTML = 'نُسخَ الرّابِط بنجاح!'; else msg.innerHTML = 'هناك خطأ ما! أعد المُحاولة رجاء'; } catch(err) { msg.innerHTML = 'المُتصفّح لا يدعم هذه العمليّة'; } }
الدّالة request مسؤولة عن تنفيذ طلب XMLHttpRequest، حيث تستقبل الرّابِط الأصلي ثمّ تقوم الدّالة callback
باستقبال الجواب (أي المُعرّف الخاصّ بالرّابط)، ثمّ تقوم بإسناده إلى العنصر الذي يحمل المُعرّف result
في صفحة HTML (أي حقل النّتيجة).
لاحظ بأنّنا استخدمنا الخاصيّة window.location.host
للحصول على اسم النّطاق، وذلك لمرونة أكثر بحيث لا نضطر إلى تغييره يدويا كلّما غيّرنا نطاق التّطبيق أو المُستضيف، والأمر مُفيد كذلك إذا أردت استخدام أكثر من اسم نطاق واحد.
الدّالة copy
تقوم بالحصول على قيمة النّتيجة (أي الرّابط المُختصر) ثمّ تعتمد على التّابع select
لتضليل النّتيجة، وبعدها نقوم بمُحاولة تنفيذ الأمر copy
بالسّطر:
var copy = document.execCommand('copy');
فإن لم يكن المُتصفّح يدعم هذه العمليّة (إمّا لقِدَمِ إصداره أو لسبب آخر) فستُعرَض للمُستخدم رسالة تُفيد بأنّ هذه العمليّة غير ممكنة لكي ينتبه وينسخه يدويّا.
نشر التّطبيق على منصّة Heroku.
الآن وقد أصبح تطبيقنا كاملا ويعمل بشكل جيّد في بيئة التّطوير (المضيف المحلي) حان الوقت لرفعه إلى منصّة Heroku ونشره للعالم ليتمكّن الجميع من استخدامه. لكن قبل ذلك يجب أن نقوم ببعض التّعديلات.
أولا غيّر خيار تصحيح الأخطاء، بتعديل السّطر التّالي:
app.run(debug=True, host='0.0.0.0')
إلى ما يلي:
app.run(host='0.0.0.0')
وبما أنّ Heroku يعتمد على نظام Postgresql لإدارة قاعدة البيانات فيجب علينا تغيير رابط قاعدة البيانات.
الجميل في منصّة Heroku هي إمكانيّة الوصول إلى رابط قاعدة البيانات عن طريق مُتغيّر بيئة، وهذا المُتغيّر يُسمى DATABASE_URL
وللوصول إى قيمته يكفي الاعتماد على الوحدة os
مع الكائن environ
وطريقة الوصول إلى قيمة هذا المُتغيّر هي كالآتي:
os.environ['DATABASE_URL']
لكن لا تنس أن تسترد الوحدة os
في أعلى الملف:
import os
وبالتّالي فالتّغيير الذي يجب علينا القيام به هو تعويض السّطر الأول بالسّطر الثّاني في الشّيفرة التّاليّة:
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL']
سنقوم بتنصيب حزمة psycopg2
ليتمكّن SQLAlchemy من التّعامل مع قواعد بيانات Postgresql وسنستخدم خادوم gunicorn
لنشر التّطبيق، لذلك عليك تنصيبه كذلك (تأكّد من أن البيئة الوهميّة لا تزال مُفعّلة):
pip install psycopg2 gunicorn
سيتوجّب علينا كذلك إنشاء ملفّ باسم requirements.txt
لتعريف Heroku بمُتطلّبات التّطبيق من حزم ووحدات، وذلك ليقوم بتنصيبها عند النّشر.
لن نقوم بإنشاء هذا الملفّ يدويا، وسنستعمل أداة pip
لإنشاء الملفّ، تأكّد فقط بأنّك لا تزال تعمل تحت البيئة الوهميّة ثمّ نفّذ الأمر التّالي لإنشاء الملفّ:
pip freeze > requirements.txt
بعد انتهاء التّنفيذ سيظهر ملفّ جديد باسم requirements.txt
وستكون مُحتوياته شيئا مُشابها لما يلي (ربّما تتغيّر أرقام الإصدارات أو قد تظهر حزم جديدة حسب تاريخ تطبيقك لهذا المشروع):
click==6.6 Flask==0.11.1 Flask-SQLAlchemy==2.1 gunicorn==19.6.0 hashids==1.1.0 itsdangerous==0.24 Jinja2==2.8 MarkupSafe==0.23 psycopg2==2.6.2 SQLAlchemy==1.0.14 Werkzeug==0.11.10
هذه هي الاعتماديات (أو الحزم التي يعتمد عليها التّطبيق) التي يعتمد عليها تطبيقنا، ولو استخدمت إضافة من إضافات Flask (Flask-login على سبيل المثال) لَظهَرتْ في هذا الملف.
يجب كذلك إنشاء ملفّ باسمProcfile
لتعريف منصّة Heroku بملفّ التّطبيق الرّئيسيّ، وسيحتوي هذا الملفّ ما يلي:
web: gunicorn app:app
لاحظ بأنّ الاسم app
الأول هو المهم، وهو اسم ملفّ التّطبيق (أي app.py
) ولو كان اسم الملف الرّئيسي مثلا run.py
لكان مُحتوى ملفّ Procfile
كالآتي:
web: gunicorn run:app
عليك كذلك تنصيب أداة git لتتمكّن من نشر التّطبيق ورفعه إلى المنصّة.
التّسجيل في منصّة Heroku
لتسجيل حساب جديد في منصّة Heroku ادخل إلى هذا الرّابط ، ثمّ املأ الحقول بما يُناسب، ويُمكنك ترك خانة Company name فارغة إن أردت.
عند ملء النّموذج سيكون كالتّالي:
اضغط على Create Free Account ثمّ فعّل بريدك الإلكتروني، بعد النّقر على رابط تفعيل البريد الإلكتروني ستنتقل إلى صفحة يُطلب منك فيها تعيين كلمة مرور وإعادة كتابتها كإجراء احتياطي. بعدها اضغط على Set password and log in (الخانة التي تسألك عمّا إذا كنت تريد الحصول على مُحتوى تقني عبر بريدك بشكل دوري ليست مُهمّة ولك كامل الحريّة في الاختيار بين القبول أو ضدّه).
بعد تعيين كلمة المرور ستنتقل إلى صفحة ترحيب مع رابط للمُتابعة إلى لوحة التحكم لتستطيع إنشاء التّطبيقات.
إنشاء التطبيق
بعد أن وصلت إلى لوحة التّحكم، يُمكنك الآن إنشاء تطبيق عبر الضّغط على زر “Create New App”، يُمكنك تعيين اسم للتّطبيق في خانة “App Name” سيكون هذا الاسم الذي ستختاره مُتواجدا في عنوان URL التّطبيق، ويُمكنك تركه فارغا وسيختار Heroku اسما عشوائيّا مُتاحا. ويُمكنك كذلك تعديل المنطقة الجغرافيّة للخادوم إن أردت.
بعد الانتهاء، اضغط على “Create App” لتُنشئ التّطبيق، تبقى لنا خطوة أخرى وهي تنصيب أداة Heroku Toolbelt التّي تُمكّننا من إدارة التّطبيقات عن طريق سطر الأوامر.
لتنصيب Heroku Toolbelt انتقل إلى هذا الرّابط واختر نظام التّشغيل الخاص بك وقم بالتّنصيب بالطّريقة الاعتياديّة. بالنّسبة لمُستخدمي توزيعة Debian أو ما بُنيَ عليه من توزيعات يُمكنك تنفيذ الأمر التّالي على الطّرفيّة:
$ wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh
الآن بعد تنصيب الأداة، يُمكنك تسجيل دخولك إلى منصّة Heroku عبر سطر الأوامر، وذلك بتنفيذ الأمر:
$ heroku login
بعد إدخال بريدك الإلكتروني وكلمة المرور ستُلاحظ رسالة كالآتي:
Logged in as email@example.com
بعدها أنشئ مُستودع git في مُجلّد التّطبيق واربطه مع المستودع الخاص بالمنصة عن طريق تنفيذ الأوامر التّاليّة:
$ git init $ heroku git:remote -a app-name
مع استبدال app-name
باسم التّطبيق الذي اخترته (إن لم تختره فستجده في هذه الصّفحة )
يُفضّل إضافة مجلّد venv
الخاصّ بالبيئة الوهميّة إلى ملفّ .gitignore
لتجاهله.
بعدها يُمكنك نشر التّطبيق عن طريق الأوامر التّالية:
$ git add . $ git commit -am "initial commit" $ git push heroku master
بعد أن تُرفَع الملفّات بنجاح، ستهتم منصّة Heroku بتنصيب الحزم اللازمة عن طريق ملف requirements.txt
الذي أعددناه سابقا.
بعد انتهاء الأمر، بقيت خطوة أخيرة، وهي خطوة إنشاء جدول قاعدة البيانات، وللقيام بذلك اذهب إلى هذا الرّابط:
https://dashboard.heroku.com/apps/app-name/resources
مع تغيير app-name
إلى اسم تطبيقك.
وابحث في خانة “Quickly add add-ons from Elements” عن إضافة Heroku Postgres ثمّ اضغط على زر Provision، وبعدها يكفي تنفيذ الأمر التّالي على سطر الأوامر لإنشاء قاعدة البيانات والجدول الخاص بالرّوابط:
heroku run python create_db.py
إذا لاحظت رسالة مُشابهة لما يلي فلا تقلق فهي مُجرّد تنبيه ولا تُشكل أيّة مُشكلة:
warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.')
بعد الانتهاء من الخطوة السّابقة سيتكون قد أكملت جميع الخطوات اللازمة لتطوير تطبيق ونشره للعالم ويُمكنك زيارة تطبيقك عبر عنوان URL الخاص به أو تنفيذ الأمر التّالي من سطر الأوامر:
heroku open
ختاما
بعد أن أنهينا التّطبيق يجب أن تكون قادرا على فهم كيفيّة عمل تطبيقات اختصار الرّوابط، ويجب عليك أن تكون قادرا على نشر تطبيقاتك على منصّة Heroku دون مشاكل، وإن واجهت أية مُشكلة أو أردت الاستفسار عن هذا التّطبيق، يُمكنك طرح سؤالك في قسم الأسئلة والأجوبة.
وأنبّه إلى أنّ هذا المشروع لم يكن للقارئ المبتدئ وإذا واجهت مشاكل مع هذا المشروع أو وجدته مُعقّدا بعض الشيء، فلا تقلق وتابع جديد الأكاديميّة لأنّنا سننشر سلسلة أخرى أكثر تفصيلا عن إطار العمل Flask فكن في الموعد.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.