سننشئ في هذه المقالة تطبيق جانغو مهمته عرض أحوال الطقس الحالية لعدّة مدن.
ستتولى واجهة برمجة التطبيقات لخرائط الطقس المفتوحة Open Weather Map API مسؤولية توفير بيانات الطقس الحالية. سنستخدم في عملنا قاعدة بيانات وننشئ نموذجًا، بحيث يمكن تطبيق ما سنتعلمه هنا لاحقًا في المشاريع الأعقد.
المتطلبات الأساسية
يلزم لهذا المشروع تثبيت بايثون Python على جهازك، وأن تتمكن من الرجوع إلى هذه السلسلة من المقالات التعليمية إذا احتجت إلى معلومات أكثر.
كُتبت الشيفرة المكتوبة في مقالنا هذا ببايثون 3 وجانغو 3.0، ولذلك لا بُد أن تكون ملمًا بهما جيدًا.
الخطوة الأولى - تجهيز المشروع
من السهل تثبيت جانغو كما هو حال أي مكتبة من مكتبات بايثون، بأحد الطريقتين التاليتين:
-
فتح بيئة افتراضية وتنفيذ الأمر
pip
لتثبيت جانغو. -
إنشاء مجلد مشروع وتشغيل أداة
pipenv
، ثم تفعيل صدفةpipenv
.
وتؤدي كلتا الطريقتين الغرض، لكننا سنستخدم في مقالتنا هذه أداة pipenv
.
ملاحظة: يجب أن تكون قادرًا على الرجوع إلى هذه السلسلة من المقالات التعليمية إذا أردت استخدام طرق تثبيت جانغو الأخرى.
يحتوي التوثيق الرسمي لجانغو على تعليمات تثبيت pipenv
، إما باستخدام Homebrew، أو Linuxbrew. يمكنك أيضًا تثبيت pipenv
باستخدام pip
.
أنشئ باستخدام نافذة الطرفية مجلدًا للبيئة:
$ mkdir the_weather_env
ثم انتقل إلى داخله:
$ cd the_weather_env
ثم استخدم pipenv
لتثبيت جانغو:
$ pipenv install django
سيؤدي هذا إلى تثبيت آخر إصدار من جانغو على جهازك، وفي حالتنا كان آخر إصدار هو 3.0.5.
استخدم أيضًا pipenv
لتثبيت مكتبة الطلبات Request التي ستستخدمها فيما بعد:
$ pipenv install requests
فعّل البيئة الافتراضية virtualenv
للمشروع بتنفيذ الأمر التالي في الطرفية:
$ pipenv shell
سيولد هذا عمليةً فرعيةً جديدةً للصدفة.
الخطوة الثانية - افتتاح مشروع جانغو
بعد أن تنتهي من تثبيت جانغو أنشئ مجلدًا لهذا المشروع وانتقل إليه (إذا لم تكن قد فعلت ذلك).
يمكنك تنفيذ الأمر startproject
الذي يوفره جانغو لتولّد المشروع.
(the_weather_env) django-admin startproject the_weather
سيكون جانغو قد أنشأ بعد هذا الأمر بضعة ملفات في المجلد الذي تعمل فيه.
لنجرب الآن تشغيل خادم التطوير، انتقل إلى المجلد الجديد في الطرفية:
(the_weather_env) cd the_weather
والآن استخدم manage.py لتنفيذ الأمر unserver
في الطرفية:
(the_weather_env) python manage.py runserver
سترى إذا دققت في الطرفية عنوان محدد الموارد الموحد URL لتطبيقك الذي يجب أن تكون قيمته الافتراضية هي "127.0.0.1:8000"، كما هو موضح في الصورة التالية:
افتح الآن متصفح الويب الذي تستخدمه واذهب إلى ذلك العنوان:
إذا كانت الصفحة صفحة تهنئة فاعلم أنك نجحت في إعداد جانغو بسلام.
الخطوة الثالثة - تسجيل الدخول إلى لوحة تحكم الإدارة
الآن سندخل إلى لوحة الإدارة التي يوفرها لنا جانغو. لكن يجب أولًا تهجير قاعدة البيانات التي نعمل عليها وهذا يعني أن ينشئ جانغو الجداول المعرفة مسبقًا والضرورية للتطبيقات الافتراضية.
نحتاج أولًا لإيقاف تشغيل الخادم بالضغط إما على المفتاحين "CONTROL+C"، أو "CTRL+C" بحسب البيئة المُستخدمة، ثم ننفذ الأمر migrate
في الطرفية:
(the_weather_env) python manage.py migrate
سينشئ جانغو عندئذٍ قاعدة بيانات SQLite وهي الافتراضية في الإعدادات، وسيضيف عدة جداول إليها. إذا رأيت في مجلد المشروع ملفًا جديدًا اسمه "db.sqlite3" فاعلم أن قاعدة البيانات قد أنشئت.
من الجداول التي يوفرها جانغو: جدول المستخدمين user table، الذي يخزن بيانات مستخدمي التطبيق، ولن نحتاج في تطبيقنا الذي نعمل عليه لأي مستخدمين باستثناء المستخدم المدير admin الذي يمكّننا من الوصول إلى لوحة تحكم الإدارة.
وعلى هذا، لننشئ مستخدم المدير بتنفيذ الأمر createsuperuser
في الطرفية:
(the_weather_env) python manage.py createsuperuser
سيُطلب منك تحديد اسم المستخدم وعنوان البريد الإلكتروني وكلمة المرور، اكتبها ثم أعد تشغيل الخادم في الطرفية:
(the_weather_env) python manage.py runserver
اذهب من شاشة المتصفح إلى العنوان "127.0.0.1:8000/admin" الذي هو عنوان لوحة تحكم المدير، وننوه هنا إلى أن إعداد المستخدم admin ضمن الملف "urls.py" هو الذي مكّنك من الذهاب إلى تلك الصفحة.
وعند تسجيل دخولك باسم المستخدم وكلمة المرور اللذين اخترتهما للتو فستدخل إلى لوحة إدارة جانغو.
يظهر في الصورة السابقة نموذجان يتيح لك جانغو الوصول إليهما، وهما: Groups و Users؛ إذ أن النماذج في حقيقتها ما هي إلا تمثيلات لجداول قاعدة البيانات. لذلك، هذان النموذجان انعكاسًا لجدولي قاعدة البيانات المقابلين، ومع أن جانغو قد أنشأ جداول أخرى غيرهما، إلا أنه لا حاجة بنا للوصول إليها مباشرةً لذا لم تُنشأ نماذج تقابلها.
إذا نقرت على Users ستظهر لك تفاصيل أوسع عن جدول المستخدمين وسترى المستخدم الذي أنشاته. اقض بعض الوقت في استكشاف لوحة الإدارة بالنقر على الروابط المختلفة لرؤية ما هو موجود، لكن حذارِ أن تحذف المستخدم لكي لا تضطر إلى تنفيذ الأمر createsuperuser
مجددًا.
دعنا نغادر لوحة الإدارة الآن ونركز على كتابة الشيفرة. ستحتاج إلى إنشاء تطبيق داخل مشروعك ليجلب لنا معلومات حالة الطقس.
الخطوة الرابعة - إنشاء التطبيق
يمكّننا جانغو من فصل الوظائف البرمجية عن بعضها بعضًا في المشروع الواحد باستخدام التطبيقات، فكل تطبيق يؤدي وظيفة معينة مُكلفٌ بها ضمن المشروع الواحد؛ فإذا نظرنا إلى الملف "settings.py" على سبيل المثال، فسنرى قائمة التطبيقات المثبتة "INSTALLED_APPS". وأول التطبيقات المثبتة هو "django.contrib.admin" الذي استخدمته للتو، إذ يتولى هذا التطبيق مسؤولية وظائف الإدارة فقط ولا شيء غير ذلك. مثال آخر على تطبيق موجود في المشروع افتراضيًّا، هو التطبيق "django.contrib.auth" الذي سمح لنا بتسجيل الدخول إلى لوحة الإدارة.
نحتاج في حالتنا إلى إنشاء تطبيق جديد يتولى مهمة إظهار حالة الطقس.
أوقف تشغيل الخادم أولًا، ثم نفذ الأمر startapp
في الطرفية:
(the_weather_env) python manage.py startapp weather
سيضيف جانغو عند تنفيذ هذا الأمر مجلدًا جديدًا وبعض الملفات إلى المشروع.
دعنا ننشئ مع الملفات التي وُلِّدت للتو ملفًا جديدًا اسمه "urls.py" في مجلد التطبيق weather:
from django.urls import path urlpatterns = [ ]
هذا الملف مماثل للملف "urls.py" في مجلد "the_weather"، ويتمثّل الفرق بينهما هو أن هذا الملف "urls.py" يحتوي على جميع عناوين URL المرتبطة بالتطبيق نفسه.
لم تحدِّد أي عناوين URL بعد، لكن يمكنك إعداد المشروع لكي يتعرف على تطبيقك ويوجه أي عناوين URL معينة لتطبيقك إلى ملف التطبيق "urls.py".
اذهب إلى قائمة التطبيقات المثبتة INSTALLED_APPS
في الملف settings.py وأضف اسم التطبيق weather
إلى القائمة:
... INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'weather', ] ...
وبهذا تخبر جانغو أنك تريد استخدام التطبيق "weather" في مشروعك، وعندئذ سيعلم جانغو أين سيبحث عن ملفات التهجير وعناوين URL.
ستحتاج الآن إلى تعديل الملف الأصلي urls.py بحيث يشير إلى ملف urls.py الذي في التطبيق، ولذلك أضف سطرًا تحت المسار الموجود للوحة الإدارة، كما ستحتاج أيضًا إلى استيراد المكتبة include
لتتمكن من الإشارة إلى ملف urls.py للتطبيق:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('weather.urls')), ]
تعني السلسلة الفارغة أنك لن تحتاج لاستخدام نقطة نهاية من أجل نقطة الدخول إلى تطبيقنا، بل سنترك للتطبيق مهمة معالجة أي نقاط نهاية محددة، وبالرفم من أنه كان بإمكاننا وضع شيء على نحو (...,'/path('weather
، والذي كان سيُلزِمنا بكتابة /127.0.0.1:8000/weather للحصول على أي شيء مرافق لتطبيق الطقس، لكن لأن مشروعنا بسيط أصلًا فلن نفعل هذا هنا.
الخطوة الخامسة - إضافة القالب والعرض
سنحتاج الآن لإضافة القالب إلى المشروع الذي نعمل عليه؛ والقالب في جانغو ما هو إلا ملف HTML يتيح لنا تعليمات أوسع في شيفرته، الأمر الذي يجعل القالب ديناميكيًا، إذ سنتمكن فيه من معالجة وظائف، مثل إضافة المتغيرات والتعليمات الشرطية if والحلقات.
نذهب في الطرفية إلى مجلد التطبيق "weather":
(the_weather_env) cd weather
ثم ننشئ المجلد "templates":
(the_weather_env) mkdir templates
ثم ننتقل إلى داخله:
(the_weather_env) cd templates
أنشئ مجلدًا آخر يحمل نفس اسم التطبيق، لأن جانغو يدمج جميع مجلدات القوالب من التطبيقات الموجودة سابقًا لدينا معًا، وللحيلولة دون تكرار أسماء الملفات، يمكنك استخدام اسم التطبيق:
(the_weather_env) mkdir weather
من داخل مجلد weather هذا، أنشئ ملفًا جديدًا اسمه index.html الذي سيكون القالب الأساسي.
وفيما يلي شيفرة HTML التي ستستخدمها للقالب:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>What's the weather like?</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.css" /> </head> <body> <section class="hero is-primary"> <div class="hero-body"> <div class="container"> <h1 class="title"> What's the weather like? </h1> </div> </div> </section> <section class="section"> <div class="container"> <div class="columns"> <div class="column is-offset-4 is-4"> <form method="POST"> <div class="field has-addons"> <div class="control is-expanded"> <input class="input" type="text" placeholder="City Name"> </div> <div class="control"> <button class="button is-info"> Add City </button> </div> </div> </form> </div> </div> </div> </section> <section class="section"> <div class="container"> <div class="columns"> <div class="column is-offset-4 is-4"> <div class="box"> <article class="media"> <div class="media-left"> <figure class="image is-50x50"> <img src="http://openweathermap.org/img/w/10d.png" alt="Image"> </figure> </div> <div class="media-content"> <div class="content"> <p> <span class="title">Las Vegas</span> <br> <span class="subtitle">29° F</span> <br> thunderstorm with heavy rain </p> </div> </div> </article> </div> </div> </div> </div> </section> <footer class="footer"> </footer> </body> </html>
ملاحظة: استخدمنا مكتبة بولما Bulma خلف الكواليس لمعالجة التنسيقات styling والتخطيطات layout.
بعد أن فرغت من إنشاء القالب ستنشئ مزيجًا يضم عرضًا view وعنوان URL معًا، لتتمكن من رؤية هذا فعليًا في التطبيق؛ والعروض في جانغو هي إما دوال أو أصناف، وفي حالتنا هذه ونظرًا لأنك تنشئ عرضًا بسيطًا فستنشئ دالةً، ثم تضيف هذه الدالة إلى ملف views.py:
from django.shortcuts import render def index(request): return render(request, 'weather/index.html') #returns the index.html template
سُمّي العرض باسم "index" لأنه سيكون في فهرس التطبيق الذي هو عنوان URL الجذر. لا بُد من إعادة request
لتصيير القالب، لأنه ضروري لدالة render
واسم ملف القالب الذي تريد تصييره، والذي هو في حالتنا weather/index.html.
دعنا الآن نضيف عنوان URL الذي سيرسل الطلب إلى هذا العرض. لذلك، حدِّث القائمة urlpatterns
في ملف urls.py للتطبيق كما يلي:
from django.urls import path from . import views urlpatterns = [ path('', views.index), #the path for our index view ]
يتيح لك هذا فهرسة العرض الذي أنشأته للتو.
سيطابق جانغو أي عنوان URL ليس لديه نقطة نهاية ويوجهه إلى تابع العرض الذي أنشأته.
الآن، اذهب إلى نافذة الطرفية وعد فيها إلى جذر المشروع (the_weather)، ثم شغّل الخادم:
(the_weather_env) python manage.py runserver
ثم افتح متصفح الويب واذهب للعنوان 127.0.0.1:8000 مرةً أخرى.
سترى صفحة HTML المُصيرة للملف index.html، ويوجد فيها حقل يمكّنك من إضافة مدينة، ويظهر أيضًا قيمةٌ ضمنيةٌ مسبقةٌ لطقس لاس فيجاس، لكن ما يزال النموذج غير جاهز والطقس في الوقت الحالي هو مجرد موضع مؤقت placeholder، لذا سنعمل على هذه الأمور في الخطوات التالية.
الخطوة السادسة - استخدام واجهة برمجة تطبيقات الطقس Weather API
يجب عليك أولًا إنشاء حساب في موقع واجهة برمجة تطبيقات الطقس. وهو التطبيق الذي سيوفر لك معلومات الطقس في الزمن الحقيقي لأي مدن تختار إضافتها إلى التطبيق.
لذا، اذهب إلى الموقع وأنشئ حسابًا، ثم اذهب إلى مفاتيح واجهة برمجة التطبيقات في لوحة التحكم التي لديهم، ويمكنك استخدام المفتاح الافتراضي الذي يزودونك به، أو أن تنشئ مفتاحًا جديدًا لواجهة برمجة التطبيقات؛ إذ سيتيح لك هذا المفتاح استخدام واجهة برمجة التطبيقات للحصول على حالة الطقس.
ملاحظة: من المهم الحفاظ على سرية مفاتيح واجهة برمجة التطبيقات الطقس لمنع الأطراف الخارجية من استخدامها. تخيل ماذا سيحدث لو رُبِط مفتاح واجهة برمجة التطبيقات بمستودع بعيد مثل مستودعات Github. لا أعتقد أن أحدًا منا يرغب في أن يحدث هذا معه.
نقطة النهاية الوحيدة التي ستستخدمها موضحةٌ فيما يلي، إذ يمكنك رؤية البيانات المعادة بتعديل عنوان URL التالي بحيث يحتوي مفتاح واجهة برمجة التطبيقات، ثم الذهاب إلى عنوان URL في المتصفح:
http://api.openweathermap.org/data/2.5/weather?q=las%20vegas&units=imperial&appid=YOUR_APP_KEY
يستغرق تفعيل مفتاح واجهة برمجة التطبيقات بعض الوقت، لذا إذا لم يعمل في بادئ الأمر فانتظر بضع دقائق، ثم كرّر المحاولة.
من المتوقع الحصول على استجابة بصيغة JSON تحتوي على الإحداثيات ودرجات الحرارة وأحوال الطقس.
دعنا الآن نضيف طلبًا للحصول على البيانات وإخراجها إلى التطبيق، ونعدّل العرض index
لإرسال طلب إلى عنوان URL الذي لديك.
from django.shortcuts import render import requests def index(request): url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY' city = 'Las Vegas' city_weather = requests.get(url.format(city)).json() #request the API data and convert the JSON to Python data types return render(request, 'weather/index.html') #returns the index.html template
أضف الآن import requests
و url
و city
و city_weather
.
ما فعلته في السطور السابقة الجديدة هو أنك أضفت عنوان URL الذي سترسِل الطلب إليه، ونلاحظ اختلاف عنوان URL قليلًا عن عنوان URL الذي اختبرته من قبل في المتصفح، فالمدينة هنا ليست جزءًا من URL بل أصبحت داخل متغير، وبهذا سيمكنك هذا النمط من تبديل أسماء مدن أخرى في المستقبل.
سنعطي في الوقت الحالي القيمة الثابتة "Las Vegas" للمدينة city
، لكن في المستقبل ستحدّد بقيم المدن الموجودة في قاعدة البيانات. أخيرًا، سترسل الطلب إلى عنوان URL باستخدام المدينة وتحصل على تمثيل JSON لتلك المدينة.
إذا جربت طباعة print
النتيجة إلى الطرفية، ستتمكن من رؤية نفس البيانات التي حصلت عليها عندما وضعت عنوان URL في شريط العنوان:
... def index(request): ... print(city_weather) #temporarily view output return render(request, 'weather/index.html') #returns the index.html template
إذا أعدت تحميل الصفحة في المتصفح فسترى أن البيانات طُبعت إلى الطرفية. كان الغرض من إضافة تعليمة print
هو التحقق من صحة ما ذكرناه. الآن وقد حصل ذلك، سنحذف تعليمة print
من الشيفرة.
الخطوة السابعة - عرض البيانات في القالب
ستحتاج في هذه الخطوة لتمرير البيانات إلى القالب لعرضها على المستخدم.
لننشئ قاموسًا يخزن كافة البيانات التي تحتاجها. ستحتاج من بين البيانات المعادة temp
و description
و icon
.
... def index(request): ... weather = { 'city' : city, 'temperature' : city_weather['main']['temp'], 'description' : city_weather['weather'][0]['description'], 'icon' : city_weather['weather'][0]['icon'] } return render(request, 'weather/index.html') #returns the index.html template
الآن وقد بات لديك كل المعلومات التي تريدها، يمكنك أن تمررها إلى القالب، ولذلك ستنشئ متغيرًا اسمه context
سيكون قاموسًا يسمح لك باستخدام قيَمِهِ داخل القالب، ثم ستضيف في الدالة render
وسيطًا ثالثًا هو context
كما يلي:
... def index(request): ... context = {'weather' : weather} return render(request, 'weather/index.html', context) #returns the index.html template
وهكذا بعد أن أصبحت بيانات الطقس داخل الـمتغير context
، دعنا نذهب إلى القالب لنضيف هذه البيانات؛ فكل ما تحتاج فعله داخل القالب index.html هو تعديل شيفرة HTML لتستخدم المتغيرات بدلًا من استخدام القيم المسبقة الضمنية، إذ ستستخدِم هذه المتغيّرات الوسوم {{ }}، وستسنِد reference كل شيء داخل قاموس context
.
نلاحظ أن جانغو يحوّل قيم القاموس، بحيث لا يمكن الوصول إليها إلا باستخدام صيغة الاستدعاء النقطية dot notation، إذ سنحصل مثلًا عند استخدام weather.city
على اسم المدينة. لا تستخدم ['weather['city
كما هو مُستخدم في بايثون.
ابحث عن الصندوق <div>
وعدّله ليستخدم المتغيرات:
... <div class="box"> <article class="media"> <div class="media-left"> <figure class="image is-50x50"> <img src="http://openweathermap.org/img/w/{{ weather.icon }}.png" alt="Image"> </figure> </div> <div class="media-content"> <div class="content"> <p> <span class="title">{{ weather.city }}</span> <br> <span class="subtitle">{{ weather.temperature }}° F</span> <br> {{ weather.description }} </p> </div> </div> </article> </div> ...
وهكذا بعد استبدال جميع المتغيرات، ستحصل على قيم الطقس الحالية للمدينة التي حددتها.
لكن ما تزال المدينة تظهر قيمتها ضمنية المسبقة، لذا فما ستفعله الآن هو سحب القيم من قاعدة البيانات وعرض بيانات المدن الموجودة فيها.
أنشئ لهذا الغرض جدولًا في قاعدة البيانات يحتوي أسماء المدن التي تريد معرفة حالة طقسها، وهذا يعني بطبيعة الحال أننا سننشئ نموذجًا مقابلًا له.
اذهب إلى الملف "models.py" في التطبيق "weather" وأضف الشيفرة التالية:
from django.db import models class City(models.Model): name = models.CharField(max_length=25) def __str__(self): #show the actual city name on the dashboard return self.name class Meta: #show the plural of city as cities instead of citys verbose_name_plural = 'cities'
سينشئ هذه الشيفرة جدولًا في قاعدة البيانات بعمود اسمه name
يدل على اسم المدينة، وسيكون نوع المدينة هو charfield
أي سلسلة عاديّة. ولقبول هذه التغيرات وتطبيقها على قاعدة البيانات، ستحتاج لتنفيذ الأمر makemigrations
الذي سيولد الشيفرة التي ستحدِّث قاعدة البيانات وتجري عمليات التهجير إليها.
دعنا نوقف تشغيل الخادم وننفذ تلك التهجيرات في نافذة الطرفية:
(the_weather_env) python manage.py makemigrations
ثم نهجّر:
(the_weather_env) python manage.py migrate
نحتاج لتمكين رؤية النموذج في لوحة الإدارة، ولهذا لا بُد من تسجيله في الملف "admin.py" كما يلي:
from django.contrib import admin from .models import City admin.site.register(City)
الآن نعيد تشغيل الخادم وننظر في لوحة الإدارة في المتصفح:
كما نرى فقد أصبحت City الآن أحد الخيارات.
يمكن بعد ذلك الذهاب إلى لوحة الإدارة وإضافة بعض المدن. على سبيل المثال: لندن وطوكيو ولاس فيجاس.
مع وجود هذه الإدخالات في قاعدة البيانات، ستحتاج الآن إلى الاستعلام عنها وإظهارها في العرض. ابدأ باستيراد النموذج City
ومن ثم الاستعلام منه عن جميع الكائنات.
from django.shortcuts import render import requests from .models import City
ثم نحدّث الطلب request
بالمدن cities
:
... def index(request): url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY' cities = City.objects.all() #return all the cities in the database ...
الآن وقد أصبحت لديك قائمة المدن، ستحتاج إلى المرور فيها جميعًا بحلقة تكرار وجلب حالة الطقس لكل منها وإضافتها جميعًا إلى قائمةٍ ستُمرّر في نهاية الأمر إلى القالب، وسيكون هذا مجرد شكلٍ آخر لما فعلناه في خطوة سابقة؛ والفرق هو أنك تستخدم هنا المرور بحلقة مع إلحاق كل قاموس بقائمة.
ستنشئ أولًا قائمة بيانات الطقس weather_data
التي ستحتفظ بقيمة الطقس weather
لكل مدينة city
، ثم نستبدل متغيّر المدينة city
الأصلي بحلقة تمر بكل المدن cities
. بعد ذلك، يجب إلحاق كل استجابة weather
لكل مدينةcity
ببيانات الطقس weather_data
. سنحتاج أيضًا إلى تحديث السياق context
لتمرير هذه القائمة بدلًا من تمرير قاموس وحيد.
في هذه اللحظة يُفترض أن يكون الملف views.py شبيهًا بالتالي:
... def index(request): ... cities = City.objects.all() #return all the cities in the database weather_data = [] for city in cities: city_weather = requests.get(url.format(city)).json() #request the API data and convert the JSON to Python data types weather = { 'city' : city, 'temperature' : city_weather['main']['temp'], 'description' : city_weather['weather'][0]['description'], 'icon' : city_weather['weather'][0]['icon'] } weather_data.append(weather) #add the data for the current city into our list context = {'weather_data' : weather_data} return render(request, 'weather/index.html', context) #returns the index.html template
ثم ستحتاج داخل قالب index.html للمرور في هذه القائمة مستخدمًا حلقة، وتوليد شيفرة HTML لكل مدينة city
من القائمة. يمكنك لتحقيق ذلك وضع حلقة for
حول شيفرة HTML التي تولد صندوقًا وحيدًا <div>
للمدينة city
.
... <div class="column is-offset-4 is-4"> {% for weather in weather_data %} <div class="box"> <article class="media"> <div class="media-left"> <figure class="image is-50x50"> <img src="http://openweathermap.org/img/w/{{ weather.icon }}.png" alt="Image"> </figure> </div> <div class="media-content"> <div class="content"> <p> <span class="title">{{ weather.city }}</span> <br> <span class="subtitle">{{ weather.temperature }}° F</span> <br> {{ weather.description }} </p> </div> </div> </article> </div> {% endfor %} </div> …
يمكنك الآن معاينة بيانات كافة المدن التي لديك في قاعدة البيانات.
الخطوة الثامنة - إنشاء نموذج التعبئة
الخطوة الأخيرة هي السماح للمستخدم بإضافة مدينة ما مباشرةً من خلال نموذج تعبئة، ونحتاج لتحقيق هذا إلى إنشاء نموذج تعبئة. ومع أنه يمكنك تعبئته يدويًا، لكن نظرًا لأن نموذج التعبئة هذا سيحتوي نفس حقول نموذج قاعدة البيانات تمامًا، فالأسهل لك استخدام ModelForm
.
أنشئ ملفًا جديدًا باسم "forms.py" في تطبيق "weather":
from django.forms import ModelForm, TextInput from .models import City class CityForm(ModelForm): class Meta: model = City fields = ['name'] widgets = { 'name': TextInput(attrs={'class' : 'input', 'placeholder' : 'City Name'}), } #updates the input class to have the correct Bulma class and placeholder
ستحتاج لإظهار النموذج إلى إنشائه في العرض وتمريره إلى القالب، ومن أجل هذا حدّث الفهرس لإنشاء نموذج التعبئة، وستحتاج أيضًا إلى تحديث السياقcontext
لكي يُمرَّر نموذج التعبئة إلى القالب.
... from .forms import CityForm def index(request): ... form = CityForm() weather_data = [] ... context = {'weather_data' : weather_data, 'form' : form}
والآن لنحدّث قسم نموذج التعبئة ضمن القالب index.html ليستخدِم النموذج من العرض ومفتاح التشفير المساعد المُعد من أجل هجمات تزوير الطلب عبر المواقع csrf_token
، وهو ضروري لطلبات من نوع POST في جانغو.
... <form method="POST"> {% csrf_token %} <div class="field has-addons"> <div class="control is-expanded"> {{ form.name }} </div> <div class="control"> <button class="button is-info"> Add City </button> </div> </div> </form> ...
ملاحظة: تشير CSRF إلى هجمات تزوير الطلب عبر المواقع Cross-Site Request Forgery، وهي مقياس أمني لضمان إرسال بيانات نموذج التعبئة من مصدر متوقع وموثوق.
الآن وقد أصبح نموذج التعبئة في HTML يعمل، ستحتاج إلى التعامل مع بياناته لحظة دخولها إلى النموذج. ستنشئ لأجل هذا كتلة if
تتحقق من وجود طلب من نوع POST، وستحتاج أيضًا إلى إضافة التحقق من نوع الطلب قبل مباشرة التعامل مع بيانات الطقس، لتحصل آنيًا على بيانات المدينة التي تضيفها.
... def index(request): url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY' cities = City.objects.all() #return all the cities in the database if request.method == 'POST': # only true if form is submitted form = CityForm(request.POST) # add actual request data to form for processing form.save() # will validate and save if validate form = CityForm() …
وهكذا بتمرير request.POST
ستتمكن من التحقق من صلاحية بيانات النموذج.
يُفترض الآن في هذه النقطة أن تتمكن من كتابة اسم المدينة ثم النقر على إضافة "Add" ورؤيتها وهي تظهر.
أضف على سبيل المثال "Miami" اسمًا للمدينة التالية.
عندما تخرج من كتلة if
، سيُعاد إنشاء نموذج التعبئة مما يمكنك من إضافة مدينة جديدة إن شئت، وستسلك بقية الشيفرة نفس الطريقة.
وبهذا بات لدينا طريقة نتابع بها حالة الطقس لعدة مدن ضمن التطبيق.
خاتمة
عملنا في هذه المقالة مع العديد من عناصر جانغو، مثل العروض ونماذج قاعدة البيانات ونماذج التعبئة والقوالب. واحتجنا لاستخدام مكتبة بايثون "requests" لجلب بيانات الطقس الحقيقية. على الرغم من أن التطبيق بسيط، سنستخدم المفاهيم نفسها مرةً تلو الأخرى حتى في المشاريع الأعقد.
ترجمة - وبتصرف - للمقالة How To Build a Weather App in Django لصاحبها Anthony Herbert.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.