1. مقدمة

في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية مساعدة Gemini Code Assist لك في المراحل الرئيسية من دورة حياة تطوير البرامج (SDLC)، مثل التصميم والإنشاء والاختبار والتفعيل. سنصمّم تطبيقًا كاملاً ونطوّره وننشره على Google Cloud.
سننشئ واجهة برمجة تطبيقات وتطبيقًا للبحث في الجلسات ضمن فعالية تقنية. ستتضمّن كل جلسة عنوانًا وملخّصًا ومدة وفئات ومتحدثًا واحدًا أو أكثر.
المهام التي ستنفذها
- تصميم تطبيق ويب وإنشاؤه واختباره ونشره استنادًا إلى مواصفات OpenAPI من البداية
ما ستتعلمه
- كيفية استخدام Gemini Code Assist لإنشاء مواصفات OpenAPI
- كيفية استخدام ميزات إنشاء الرموز البرمجية في Gemini Code Assist لتطوير تطبيق Python Flask لمواصفات OpenAPI
- كيفية استخدام Gemini Code Assist لإنشاء واجهة أمامية على الويب لتطبيق Python Flask
- كيفية استخدام Gemini Code Assist للحصول على مساعدة بشأن كيفية نشر التطبيق على Google Cloud Run
- استخدام ميزات Gemini Code Assist، مثل "شرح الرمز البرمجي" و"إنشاء حالات الاختبار"، أثناء إنشاء التطبيق واختباره
المتطلبات
- متصفّح الويب Chrome
- حساب Gmail
- مشروع على السحابة الإلكترونية تم تفعيل الفوترة فيه
- تفعيل Gemini Code Assist لمشروعك على Google Cloud
هذا المختبر مخصّص للمطوّرين من جميع المستويات، بما في ذلك المبتدئين. على الرغم من أنّ التطبيق النموذجي مكتوب بلغة Python، ليس عليك أن تكون على دراية ببرمجة Python لفهم ما يحدث. سيكون تركيزنا على التعرّف على إمكانات Gemini Code Assist.
2. إعداد Gemini Code Assist
يغطّي هذا القسم كل ما عليك فعله لبدء هذا الدرس التطبيقي.
تفعيل Gemini Code Assist في بيئة تطوير متكاملة (IDE) في Cloud Shell
سنستخدم بيئة تطوير متكاملة (IDE) في Cloud Shell، وهي بيئة تطوير مُدارة بالكامل تستند إلى Code OSS، لبقية الدرس التطبيقي حول الترميز. علينا تفعيل ميزة "مساعد الترميز" وضبطها في بيئة التطوير المتكاملة (IDE) في Cloud Shell، وفي ما يلي الخطوات:
- انتقِل إلى ide.cloud.google.com. قد يستغرق ظهور بيئة التطوير المتكاملة بعض الوقت، لذا يُرجى الانتظار وقبول أي خيارات تلقائية للإعداد. في حال ظهور بعض التعليمات حول إعداد بيئة التطوير المتكاملة، يُرجى المتابعة وإكمالها باستخدام الإعدادات التلقائية.
- انقر على الزر رمز السحابة الإلكترونية - تسجيل الدخول في شريط الحالة أسفل الصفحة كما هو موضّح. امنح المصادقة للمكوّن الإضافي حسب التعليمات. إذا ظهرت لك الرسالة "Cloud Code - no project" في شريط الحالة، اختَرها ثم اختَر مشروع Google Cloud المحدّد من قائمة المشاريع التي تخطّط للعمل عليها.

- انقر على الزر Code Assist في أسفل يسار الصفحة كما هو موضّح، واختَر مشروع على السحابة الإلكترونية الصحيح لآخر مرة من Google. إذا طُلب منك تفعيل Cloud AI Companion API، يُرجى إجراء ذلك والمتابعة.
- بعد اختيار مشروعك على Google Cloud، تأكَّد من إمكانية رؤيته في رسالة حالة Cloud Code في شريط الحالة، ومن تفعيل Code Assist على يسار شريط الحالة كما هو موضّح أدناه:

أصبح Gemini Code Assist جاهزًا للاستخدام.
3- إعداد Firestore
Cloud Firestore هي قاعدة بيانات مستنِدة إلى مستندات وبدون خادم تتم إدارتها بالكامل، وسنستخدمها كخادم خلفي لبيانات تطبيقنا. يتم تنظيم البيانات في Cloud Firestore في مجموعات من المستندات.
علينا إنشاء مجموعة باسم sessions في قاعدة بيانات Firestore التلقائية. ستتضمّن هذه المجموعة بيانات نموذجية (مستندات) سنستخدمها بعد ذلك في تطبيقنا.
افتح "وحدة التحكّم" من داخل بيئة تطوير Cloud Shell المدمجة عبر القائمة الرئيسية كما هو موضّح أدناه:

علينا إنشاء مجموعة باسم sessions. سيحتوي هذا الحقل على قائمة بمستندات الجلسة النموذجية. سيتضمّن كل مستند السمات التالية:
- title: string
- categories: مصفوفة من السلاسل
- المتحدثون: مصفوفة من السلاسل النصية
- المدة: سلسلة
- الملخّص: سلسلة
لنملأ هذه المجموعة ببيانات نموذجية من خلال نسخ ملف يحتوي على البيانات النموذجية إلى حزمة في مشروعك، حيث يمكنك بعد ذلك استيراد المجموعة من خلال الأمر gcloud firestore import.
تهيئة قاعدة بيانات Firestore
انتقِل إلى صفحة Firestore في Cloud Console.
إذا لم يسبق لك إعداد قاعدة بيانات Firestore في المشروع، عليك إنشاء قاعدة بيانات default. أثناء إنشاء قاعدة البيانات، استخدِم القيم التالية:
- وضع Firestore:
Native - الموقع الجغرافي: اختَر نوع الموقع الجغرافي
Regionواختَر المنطقة المناسبة لتطبيقك. دوِّن هذا الموقع الجغرافي لأنّك ستحتاج إليه في الخطوة التالية لتحديد الموقع الجغرافي للحزمة. - إنشاء قاعدة البيانات

سننشئ الآن المجموعة sessions باتّباع الخطوات الواردة أدناه:
- أنشئ حزمة في مشروعك باستخدام الأمر
gsutilالموضّح أدناه. استبدِل المتغيّر<PROJECT_ID>في الأمر أدناه برقم تعريف مشروع Google Cloud. استبدِل<BUCKET_LOCATION>باسم منطقة يتوافق مع المنطقة الجغرافية لقاعدة بيانات Firestore التلقائية (كما هو موضّح في الخطوة السابقة)، ويمكن أن يكون هذا الاسم US-WEST1 أو EUROPE-WEST1 أو ASIA-EAST1 :
gsutil mb -l <BUCKET-LOCATION> gs://<PROJECT_ID>-my-bucket
- بعد إنشاء الحزمة، علينا نسخ عملية تصدير قاعدة البيانات التي أعددناها إلى هذه الحزمة، قبل أن نتمكّن من استيرادها إلى قاعدة بيانات Firebase. استخدِم الأمر الموضّح أدناه:
gsutil cp -r gs://sessions-master-database-bucket/2024-03-26T09:28:15_95256 gs://<PROJECT_ID>-my-bucket
بعد أن توفّرت لدينا البيانات المطلوب استيرادها، يمكننا الانتقال إلى الخطوة الأخيرة من عملية استيراد البيانات إلى قاعدة بيانات Firebase (default) التي أنشأناها.
- استخدِم أمر gcloud الموضّح أدناه:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2024-03-26T09:28:15_95256
سيستغرق الاستيراد بضع ثوانٍ، وبعد اكتماله، يمكنك التحقّق من صحة قاعدة بيانات Firestore والمجموعة من خلال الانتقال إلى https://console.cloud.google.com/firestore/databases، واختيار قاعدة بيانات default والمجموعة sessions كما هو موضّح أدناه:

بهذا نكون قد أكملنا إنشاء مجموعة Firestore التي سنستخدمها في تطبيقنا.
4. إنشاء نموذج التطبيق
سننشئ تطبيقًا نموذجيًا (تطبيق Python Flask) سنستخدمه في بقية الدرس التطبيقي حول الترميز. سيبحث هذا التطبيق في الجلسات المقدَّمة في مؤتمر تقني.
يُرجى اتّباع الخطوات التالية:
- انقر على اسم مشروع Google Cloud في شريط الحالة أدناه.

- ستظهر قائمة بالخيارات. انقر على تطبيق جديد من القائمة أدناه.

- اختَر تطبيق Cloud Run (سيكون هذا وقت التشغيل لتطبيقنا).
- اختَر نموذج تطبيق Python (Flask): Cloud Run.
- امنح التطبيق اسمًا واحفظه في الموقع الجغرافي المفضّل لديك.
- يؤكّد إشعار أنّه تم إنشاء تطبيقك، ويتم فتح نافذة جديدة مع تحميل تطبيقك كما هو موضّح أدناه. يتم فتح ملف
README.md. يمكنك إغلاق طريقة العرض هذه الآن.

5- التفاعل مع Gemini Code Assist
لأغراض هذا المختبر، سنستخدم Gemini Code Assist Chat المتاح داخل Cloud Shell IDE كجزء من إضافة Cloud Code في VS Code. يمكنك إظهارها من خلال النقر على زر "مساعد الترميز" في شريط التنقّل الأيمن. ابحث عن رمز "مساعد الترميز"
في شريط أدوات التنقّل الأيمن وانقر عليه.
سيؤدي ذلك إلى فتح لوحة دردشة Code Assist داخل بيئة تطوير متكاملة (IDE) في Cloud Shell، ويمكنك الدردشة مع Code Assist.

لاحظ رمز سلة المهملات في أعلى الصفحة، فهو يتيح لك إعادة ضبط سياق سجلّ محادثات Code Assist. يُرجى العِلم أيضًا أنّ هذه المحادثة مرتبطة بسياق الملفات التي تعمل عليها في بيئة التطوير المتكاملة.
6. تصميم واجهة برمجة التطبيقات
ستكون خطوتنا الأولى هي الاستعانة بـ Gemini Code Assist خلال مرحلة التصميم. في هذه الخطوة، سننشئ مواصفات OpenAPI للكيانات (الجلسات الفنية في حدث) التي نريد البحث فيها.
أدخِل الطلب التالي:
Generate an Open API spec that will allow me to retrieve all sessions, sessions by category, session by id. Each session has the following attributes: id, title, list of speakers, list of categories, summary and duration.
من المفترض أن يؤدي ذلك إلى إنشاء مواصفات OpenAPI للبحث في الجلسات باستخدام مَعلمات طلب بحث مختلفة. في ما يلي نموذج للمواصفات:
openapi: 3.0.0
info:
title: Sessions API
description: This API allows you to retrieve all sessions, sessions by category, and session by id.
version: 1.0.0
servers:
- url: https://sessions.example.com
paths:
/sessions:
get:
summary: Get all sessions
operationId: getSessions
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Session'
/sessions/{id}:
get:
summary: Get session by id
operationId: getSessionById
parameters:
- name: id
in: path
required: true
description: The id of the session
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Session'
/sessions/categories/{category}:
get:
summary: Get sessions by category
operationId: getSessionsByCategory
parameters:
- name: category
in: path
required: true
description: The category of the sessions
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Session'
components:
schemas:
Session:
type: object
properties:
id:
type: string
description: The id of the session
title:
type: string
description: The title of the session
speakers:
type: array
items:
type: string
description: The list of speakers for the session
categories:
type: array
items:
type: string
description: The list of categories for the session
summary:
type: string
description: The summary of the session
duration:
type: string
description: The duration of the session
يمكنك ملاحظة أنّ المواصفات تتضمّن ما يلي:
- مخطط محدّد لنوع الجلسة
- تم تحديد عدّة مسارات لواجهة برمجة التطبيقات:
/sessions/sessions/{id}/sessions/categories/{category}
أنشئ ملفًا باسم sessionsapi.yaml في المجلد العلوي وانسخ المحتوى من نافذة محادثة Code Assist باستخدام الخيار "إدراج في الملف الحالي" (الزر +) وأبقِ الملف مفتوحًا في بيئة تطوير Cloud Shell المتكاملة.
في هذه المرحلة، يمكنك ملاحظة ميزة مثيرة للاهتمام في Gemini Code Assist، وهي معلومات المقالة. يتم عرض هذه المعلومات للمطوّر عندما يقتبس الرمز البرمجي الذي تم إنشاؤه مباشرةً وبشكل مطوّل من مصدر آخر، مثل رمز برمجي حالي مفتوح المصدر. ويوفّر المصدر والترخيص للمطوّر ليقرّر ما سيفعله به.
بافتراض أنّنا موافقون على المحتوى الذي تم إنشاؤه، يمكننا الآن استخدام مستند المواصفات هذا لإنشاء تطبيق Python Flask له.
7. إنشاء التطبيق
سنطلب الآن من Code Assist إنشاء التطبيق. أدخِل الطلب التالي مع فتح ملف sessionsapi.yaml.
Generate a Python Application using the Flask framework, based on the sessionsapi.yaml file. This application uses a local in memory list of sessions. Do not use any Flask extensions.
من المفترض أن يوفّر لك ذلك هيكلاً لتطبيق Python Flask استنادًا إلى الوظائف والمسارات التي تم تحديدها في ملف مواصفات OpenAPI.
يجب أن يكون الرمز البرمجي لتطبيق Python Flask المقدَّم مشابهًا للرمز التالي:
from flask import Flask, jsonify, request
app = Flask(__name__)
sessions = [
{
"id": "1",
"title": "Session 1",
"speakers": ["Speaker 1", "Speaker 2"],
"categories": ["Category 1", "Category 2"],
"summary": "This is a summary of session 1.",
"duration": "1 hour",
},
{
"id": "2",
"title": "Session 2",
"speakers": ["Speaker 3", "Speaker 4"],
"categories": ["Category 3", "Category 4"],
"summary": "This is a summary of session 2.",
"duration": "1 hour 30 minutes",
},
]
@app.route('/sessions', methods=['GET'])
def get_sessions():
return jsonify(sessions)
@app.route('/sessions/<id>', methods=['GET'])
def get_session_by_id(id):
session = next((session for session in sessions if session['id'] == id), None)
if session is None:
return jsonify({}), 404
return jsonify(session)
@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
sessions_by_category = [session for session in sessions if category in session['categories']]
return jsonify(sessions_by_category)
if __name__ == '__main__':
app.run()
هناك ملف app.py حالي تم إنشاؤه كجزء من الخطوة السابقة. ما عليك سوى استبدال محتواه بالرمز الذي أنشأته أداة Code Assist وحفظ الملف.
نريد تغيير السطر app.run() لاستخدام المنفذ 8080 وعنوان المضيف 0.0.0.0، بالإضافة إلى التشغيل في وضع تصحيح الأخطاء أثناء التنفيذ المحلي.إليك طريقة إجراء ذلك. أولاً، لنحدّد السطر أو نختاره:
app.run()
بعد ذلك، في واجهة Code Assist Chat، اكتب الطلب: Explain this.
من المفترض أن يعرض ذلك شرحًا تفصيليًا لهذا السطر تحديدًا، كما هو موضّح في المثال أدناه:

الآن، استخدِم الطلب التالي:
update the code to run the application on port 8080, host address 0.0.0.0, and in debug mode
يجب أن يكون الرمز المقترَح الذي تم إنشاؤه على النحو التالي: :
app.run(host='0.0.0.0', port=8080, debug=True)
تذكَّر تعديل ملف app.py باستخدام هذا المقتطف.
تشغيل التطبيق محليًا
لننفّذ التطبيق على الجهاز الآن للتحقّق من متطلباته وفقًا لما بدأنا به.
تتمثل الخطوة الأولى في إنشاء بيئة Python افتراضية مع تبعيات حزمة Python في requirements.txt ليتم تثبيتها في البيئة الافتراضية. لإجراء ذلك، انتقِل إلى لوحة الأوامر (Ctrl+Shift+P) في بيئة التطوير المتكاملة في Cloud Shell واكتب إنشاء بيئة Python. اتّبِع الخطوات القليلة التالية لاختيار بيئة افتراضية (venv) ومترجم Python 3.x وملف requirements.txt.
بعد إنشاء البيئة، افتح نافذة طرفية جديدة (Ctrl+Shift+`) وأدخِل الأمر التالي:
python app.py
في ما يلي نموذج للتنفيذ:
(.venv) romin@cloudshell: $ python app.py
* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8080
* Running on http://10.88.0.3:8080
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: 132-247-368
يمكنك الآن معاينة واجهة برمجة التطبيقات على عناوين URL التالية. نفترض أنّ خادم التطوير يعمل على المنفذ 8080. إذا لم يكن كذلك، يُرجى تغييره إلى رقم المنفذ المناسب.
https://<host-name>:8080/sessionshttps://<host-name>:8080/sessions/{id}https://<host-name>:8080/sessions/categories/{category}
اتّبِع الخطوات الموضّحة أدناه للتأكّد من إمكانية استرداد بيانات JSON الواردة في الملف app.py باستخدام عناوين URL هذه:
افتح نافذة وحدة طرفية جديدة وجرِّب أيًا من الأوامر التالية:
curl -X GET http://127.0.0.1:8080/sessions
curl -X GET http://127.0.0.1:8080/sessions/<ID>
curl -X GET http://127.0.0.1:8080/sessions/categories/<CATEGORY_NAME>
8. إعادة هيكلة الرموز
بدلاً من أن يحتوي app.py على بيانات JSON نموذجية مبرمَجة بشكل ثابت، من الأفضل فصل هذه البيانات أو استخراجها إلى وحدة نمطية أخرى، حتى نتمكّن من الحفاظ على فصل واضح بين الرمز والبيانات. لنبدأ.
أبقِ ملف app.py مفتوحًا وقدِّم الطلب التالي:
Can I improve this code and separate out the sessions data from this app.py file?
من المفترض أن يقدّم لك بعض الاقتراحات حول كيفية إجراء ذلك. في ما يلي مثال على اقتراح تلقّيناه، ويجب أن تتلقّى اقتراحًا مشابهًا:

لنتبع ذلك ونفصل البيانات في ملف sessions.py كما اقترحت أداة Code Assist.
أنشئ ملفًا جديدًا باسم sessions.py
، الذي يتضمّن قائمة JSON، كما هو موضّح في البيانات التي أنشأناها أدناه:
sessions = [
{
"id": "1",
"title": "Session 1",
"speakers": ["Speaker 1", "Speaker 2"],
"categories": ["Category 1", "Category 2"],
"summary": "This is a summary of session 1.",
"duration": "1 hour",
},
{
"id": "2",
"title": "Session 2",
"speakers": ["Speaker 3", "Speaker 4"],
"categories": ["Category 3", "Category 4"],
"summary": "This is a summary of session 2.",
"duration": "1 hour 30 minutes",
},
]
تم تبسيط ملف app.py بشكل كبير، ويمكنك الاطّلاع عليه أدناه:
from flask import Flask, jsonify, request
from sessions import sessions
app = Flask(__name__)
@app.route('/sessions', methods=['GET'])
def get_sessions():
return jsonify(sessions.sessions)
@app.route('/sessions/<id>', methods=['GET'])
def get_session_by_id(id):
session = next((session for session in sessions.sessions if session['id'] == id), None)
if session is None:
return jsonify({}), 404
return jsonify(session)
@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
sessions_by_category = [session for session in sessions.sessions if category in session['categories']]
return jsonify(sessions_by_category)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=True)
تأكَّد من أنّه لا يزال بإمكانك تشغيل التطبيق على جهازك واستخدام واجهة برمجة التطبيقات مع هذه التغييرات التي تمّت إعادة هيكلتها. من المحتمل أنّ خادم تطوير Python لا يزال يعمل، لذا ما عليك سوى استرجاع أوامر curl من الخطوة السابقة.
9- الدمج مع مجموعة Firestore
الخطوة التالية هي الانتقال من قائمة JSON المحلية في الذاكرة التي لدينا للجلسات وربط تطبيقنا بمجموعة sessions في قاعدة بيانات Firestore التي أنشأناها في بداية هذا الدرس التطبيقي حول الترميز.
أبقِ ملف sessions.py مفتوحًا وقدِّم الطلب التالي:
Can you further refactor the sessions.py code to read from a Firestore database that has a collection named sessions. The collection has the same attributes as the session object that we have defined. Use the Python module google-cloud-firestore.
تلقّينا الاقتراح التالي لقراءة جميع الجلسات من مجموعة Firestore:
import google.cloud.firestore
# Create a Firestore client
db = google.cloud.firestore.Client()
# Get the sessions collection
sessions_collection = db.collection("sessions")
# Create a list of sessions
sessions = []
# Iterate over the documents and add them to the list
for doc in sessions_collection.stream():
session = doc.to_dict()
session["id"] = doc.id
sessions.append(session)
يمكنك الآن دمج الرمز في sessions.py.
إذا كان خادم Flask Development يعمل على جهازك، قد يكون تطبيقك قد أغلق مع إظهار رسالة خطأ تفيد بأنّه لم يتم العثور على وحدة Python.
يمكنك أن تطلب من "مساعد الترميز"، على سبيل المثال، معرفة وحدة Python التي يجب إضافتها إلى ملف requirements.txt، وذلك على النحو التالي:
Which Python package needs to be installed to make the firestore code work?
سيوفّر لك ذلك اسم وحدة Python (مثل google-cloud-firestore). أضِف هذا الاسم إلى ملف requirements.txt.
عليك إعادة إنشاء بيئة Python باستخدام الوحدة النمطية المضافة حديثًا (google-cloud-firestore). ولإجراء ذلك، أدخِل الأمر التالي في نافذة "Terminal" الحالية:
pip install -r requirements.txt
شغِّل التطبيق مرة أخرى (أعِد تشغيله باستخدام python app.py) وانتقِل إلى عنوان URL /sessions. من المفترض أن تظهر لك الآن المستندات النموذجية التي أضفناها إلى المجموعة sessions.

يمكنك الاستعلام عن معرّفات موارد منتظمة أخرى لاسترداد جلسات معيّنة أو جميع الجلسات لفئة معيّنة كما هو موضّح في الخطوات السابقة.
10. شرح الرمز البرمجي
يمكنك الآن استخدام ميزة "Explain this" في Gemini Code Assist للحصول على فهم جيد للرمز البرمجي. يمكنك الانتقال إلى أي من الملفات أو اختيار مقتطفات معيّنة من الرمز البرمجي وطرح أسئلة على Code Assist باستخدام الطلب التالي: Explain this.
كتمرين، انتقِل إلى ملف sessions.py وحدِّد رمز Firestore المحدّد واحصل على شرح للرمز. جرِّب أيضًا استخدام هذه الميزة على ملفات أخرى في مشروعك، وليس فقط على رمز Python.
11. إنشاء تطبيق الويب
بعد أن أنشأنا واجهة برمجة التطبيقات ودمجناها مع مجموعة Firestore مباشرة، لننشئ الآن واجهة أمامية مستندة إلى الويب للتطبيق. سيحتفظ تطبيق الويب حاليًا بوظائفه في الحد الأدنى، أي سيتمكّن من البحث عن جلسات تنتمي إلى فئة معيّنة. يُرجى العِلم أنّ لدينا مسار واجهة برمجة تطبيقات لهذا الغرض، أي /sessions/categories/{category}، لذا يجب أن يستدعي تطبيق الويب هذا المسار ويسترد النتائج.
لنبدأ مباشرةً. أدخِل الطلب التالي إلى Code Assist:
Generate a web application that allows me to search for sessions by category and uses the Flask application that we created. Please use basic HTML, CSS and JS. Embed all the Javascript and CSS code into a single HTML file only.
سيؤدي ذلك إلى إنشاء HTML لتطبيق الويب مع تضمين JavaScript وCSS فيه. سيُطلب منك أيضًا إضافة مسار جديد إلى ملف app.py، حتى يتم عرض الصفحة الرئيسية لأي مستخدم يزور عنوان URL الجذر أو الأساسي. إذا لم تذكر ذلك، يمكنك السؤال عن ذلك أو استخدام المقتطف أدناه:
@app.route('/')
def index():
return render_template('index.html')
يمكنك حفظ هذا الملف باسم index.html، ولكن قد يكون لديك سؤال حول مكان حفظ هذا الملف (أي المجلد الذي يجب حفظه فيه). يمكننا طرح سؤال متابعة على "مساعد الترميز".
Given that I am using the flask framework, where should I put the index.html file?
يجب أن يقدّم لك معلومات واضحة تفيد بأنّه يستخدم إطار عمل render_template، وبالتالي يجب وضع ملف index.html داخل المجلد templates. سيتوفّر هذا المجلد لأنّنا أنشأنا تطبيقًا استنادًا إلى نموذج Flask في بداية هذا الدرس التطبيقي حول الترميز. نتيجةً لذلك، سيكون هناك ملف index.html حالي، وما عليك سوى استبدال محتواه بالمحتوى الجديد الذي تم إنشاؤه هنا. تشير ميزة "مساعد الترميز" أيضًا إلى استيراد render_template في ملف app.py.
احفظ الرمز البرمجي لتطبيق الويب في ملف index.html وتذكَّر وضع هذا الملف في مجلد templates.
تشغيل التطبيق محليًا
لننفّذ التطبيق على الجهاز الآن للتحقّق من متطلباته وفقًا لما بدأنا به.
تأكَّد من أنّ خادم Flask المحلي لا يزال قيد التشغيل ولا يعرض أي أخطاء. في حال حدوث أخطاء، عليك معالجتها وتشغيل الخادم.
بعد تشغيل التطبيق، انتقِل إلى عنوان URL الخاص بالصفحة الرئيسية للتطبيق. يجب أن يظهر لك الملف index.html الذي تم عرضه كما هو موضّح أدناه:

قدِّم إحدى الفئات من البيانات كإدخال (مثل AI) وانقر على الزر Search. من المفترض أن يعرض هذا القسم الجلسات المصنّفة ضمن الفئة AI.

يمكنك إجراء تمرين اختياري وهو عرض بيانات وصفية إضافية، مثل المدة والفئات والمتحدثين والملخّص لكل جلسة.
12. إنشاء حالات الاختبار
لقد أنشأنا واجهة برمجة التطبيقات الخاصة بالجلسات، وحان الوقت الآن لاستخدام Gemini Code Assist لإنشاء حالات اختبار الوحدات لمسارات واجهة برمجة التطبيقات المختلفة.
أبقِ ملف app.py مفتوحًا وقدِّم الطلب التالي:
Generate unit test cases for app routes. Use unittest module.
تلقّينا الردّ التالي:
import unittest
from app import app
class FlaskAppTestCase(unittest.TestCase):
def test_index(self):
tester = app.test_client()
response = tester.get('/')
self.assertEqual(response.status_code, 200)
def test_get_sessions(self):
tester = app.test_client()
response = tester.get('/sessions')
self.assertEqual(response.status_code, 200)
def test_get_session_by_id(self):
tester = app.test_client()
response = tester.get('/sessions/1')
self.assertEqual(response.status_code, 200)
def test_get_sessions_by_category(self):
tester = app.test_client()
response = tester.get('/sessions/categories/category1')
self.assertEqual(response.status_code, 200)
if __name__ == '__main__':
unittest.main()
أنشئ ملفًا باسم tests.py يتضمّن الرمز البرمجي أعلاه.
ملاحظة حول إنشاء حالات الاختبار
قد تظهر لك قائمة رموز مختلفة عن تلك المذكورة أعلاه، وقد يتسبّب ذلك في بعض المشاكل عند تنفيذ حالات الاختبار. على سبيل المثال، لاحظنا في بعض عمليات التشغيل أنّه تم إغفال أجزاء التعليمات البرمجية الرئيسية التالية:
from app import app
الرمز أعلاه مطلوب لاستيراد تطبيق Flask الحالي الذي سننفّذ حالات الاختبار عليه.
if __name__ == '__main__':
`unittest.main()`
يلزم الرمز أعلاه لتنفيذ حالات الاختبار.
ننصحك بالاطّلاع على كل حالات الاختبار والتحقّق من assertEqual والشروط الأخرى في الرمز الذي تم إنشاؤه للتأكّد من أنّه سيعمل. بما أنّ البيانات خارجية في مجموعة Firestore، قد لا يكون لديك إذن الوصول إليها، وقد تستخدم بعض البيانات الوهمية، ونتيجةً لذلك قد تفشل الاختبارات. لذا، عدِّل حالات الاختبار وفقًا لذلك أو علِّق على بعض حالات الاختبار التي قد لا تحتاج إليها على الفور.
للتوضيح، نفّذنا أُطر الاختبار باستخدام الأمر التالي (احرص على تشغيل خادم التطوير المحلي لأنّه سيتم إجراء طلبات إلى نقاط نهاية واجهة برمجة التطبيقات المحلية):
python tests.py
حصلنا على ملخّص النتائج التالي:
Ran 4 tests in 0.274s
FAILED (failures=2)
هذا صحيح بالفعل لأنّ رقم تعريف الجلسة لم يكن صحيحًا في الاختبار الثالث، ولا توجد فئة باسم category1
.
لذا، عدِّل حالات الاختبار وفقًا لذلك وجرِّبها.
13. Test Driven Development
لنلقِ نظرة الآن على كيفية إضافة طريقة بحث جديدة في واجهة برمجة التطبيقات الخاصة بالجلسات باتّباع منهجية التطوير المستند إلى الاختبار (TDD)، والتي تتضمّن كتابة حالات الاختبار أولاً، ثم إظهار خطأ فيها بسبب عدم توفّر التنفيذ، واستخدام Gemini Code Assist لإنشاء التنفيذ المفقود حتى يجتاز الاختبار.
انتقِل إلى ملف tests.py (بافتراض أنّك عدّلت الملف tests.py ليتضمّن جميع الاختبارات التي تجتاز). اطرح الطلب التالي على Code Assist:
Generate a new test case to search for sessions by speaker
أدى ذلك إلى توفير تنفيذ حالة الاختبار التالية التي أدرجناها على النحو الواجب في ملف tests.py.
def test_get_sessions_by_speaker(self):
tester = app.test_client()
response = tester.get('/sessions/speakers/speaker1')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json, [sessions.sessions[0], sessions.sessions[1]])
إذا أجريت الاختبارات، من المفترض أن يظهر لك الخطأ التالي:
$ python tests.py
.F.
======================================================================
FAIL: test_get_sessions_by_speaker (__main__.FlaskAppTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/romin/hello-world-5/tests.py", line 21, in test_get_sessions_by_speaker
self.assertEqual(response.status_code, 200)
AssertionError: 404 != 200
----------------------------------------------------------------------
Ran 3 tests in 0.010s
FAILED (failures=1)
ويرجع ذلك إلى أنّ حالة الاختبار قد استدعت المسار التالي (/sessions/speakers/) ولا يوجد تنفيذ لذلك في app.py.
لنطلب من Code Assist أن يقدّم لنا عملية تنفيذ. انتقِل إلى الملف app.py وقدِّم الطلب التالي إلى "مساعد الترميز":
Add a new route to search for sessions by a specific speaker
حصلنا على التنفيذ التالي الذي اقترحته أداة Code Assist، وأضفناه إلى الملف app.py:
@app.route('/sessions/speakers/<speaker>', methods=['GET'])
def get_sessions_by_speaker(speaker):
sessions_by_speaker = [session for session in sessions.sessions if speaker in session['speakers']]
return jsonify(sessions_by_speaker)
أعدنا النظر في ملف tests.py وعدّلنا حالة الاختبار على النحو التالي لإجراء فحص سريع:
def test_get_sessions_by_speaker(self):
tester = app.test_client()
response = tester.get('/sessions/speakers/Romin Irani')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json), 1)
تم تشغيل الاختبار بشكل جيد. نترك لك مهمة إلقاء نظرة على حالات الاختبار التي تم إنشاؤها وتعديلها قليلاً حسب البيانات التي قد تكون لديك في Firestore، بالإضافة إلى توفير طرق assert* المناسبة في حالات اختبار الوحدات في Python.
14. النشر على Google Cloud Run
بعد أن أصبحنا مطمئنين بشأن جودة عملية التطوير، ستكون خطوتنا الأخيرة هي نشر هذا التطبيق على Google Cloud Run. ولكن ربما، من الأفضل أن نسأل "مساعد الترميز" عمّا إذا نسينا أي شيء. عند فتح app.py، أرسِل الطلب التالي :
Is there something here I should change before I deploy to production?
حسنًا أنّك سألت لأنّنا نسينا ضبط علامة تصحيح الأخطاء على "إيقاف":

كما هو موضّح، أوقِف تصحيح الأخطاء وتابِع لطلب المساعدة من Gemini Code Assist في استخدام الأمر gcloud الذي يمكن استخدامه لنشر التطبيق على Cloud Run مباشرةً من المصدر (بدون الحاجة إلى إنشاء حاوية أولاً).
أدخِل الطلب التالي:
I would like to deploy the application to Cloud Run directly from source. What is the gcloud command to do that?
جرِّب بعض الصيغ المختلفة للطلب أعلاه. جرّبنا أيضًا ما يلي:
I would like to deploy this application to Cloud Run. I don't want to build a container image locally but deploy directly from source to Cloud Run. What is the gcloud command for that?
من المفترض أن يظهر لك الأمر التالي gcloud:
gcloud run deploy sessions --source .
يمكنك أيضًا الحصول على ما يلي:
gcloud run deploy <service-name> --source . \
—-platform managed \
—-allow-unauthenticated
نفِّذ الأمر أعلاه من المجلد الجذر للتطبيق. عندما يُطلب منك إدخال region، اختَر us-central1، وعندما يُطلب منك السماح باستخدام unauthenticated invocations، اختَر Y. قد يُطلب منك أيضًا تفعيل واجهات برمجة التطبيقات من Google Cloud، مثل Artifact Registry وCloud Build وCloud Run، ومنح الإذن بإنشاء مستودع Artifact Registry. يُرجى منح الإذن.
سيستغرق اكتمال عملية النشر حوالي دقيقتَين، لذا يُرجى الانتظار.
بعد نشرها بنجاح، سيظهر لك عنوان URL لخدمة Cloud Run. انتقِل إلى عنوان URL العام هذا، ومن المفترض أن ترى تطبيق الويب نفسه الذي تم نشره وتشغيله بنجاح.

تهانينا، أحسنت!
15. (اختياري) استخدام Cloud Logging
يمكننا إعداد تسجيل الدخول في تطبيقنا بحيث يتم تجميع سجلات التطبيق في إحدى خدمات Google Cloud (Cloud Logging). يمكننا بعد ذلك استخدام ميزة Observability Gemini لفهم إدخالات السجلّ أيضًا.
لإجراء ذلك، علينا أولاً استخدام مكتبة Python Cloud Logging الحالية من Google Cloud واستخدامها لتسجيل الرسائل الإعلامية أو التحذيرية أو رسائل الخطأ (حسب مستوى السجلّ أو الخطورة).
لنحاول طرح هذا السؤال أولاً على "مساعد البرمجة". جرِّب الطلب التالي:
How do I use the google-cloud-logging package in Python?
من المفترض أن تتلقّى ردًا يتضمّن بعض المعلومات حول ذلك، كما هو موضّح أدناه:

لنضِف عبارات تسجيل إلى الدالة التي تبحث عن الجلسات حسب الفئة.
أولاً، أضِف حزمة google-cloud-logging Python إلى ملف requirements.txt.
في ما يلي مقتطف من الرمز البرمجي يوضّح كيفية دمج الرمز لتنفيذ عملية التسجيل:
...
from google.cloud import logging
...
app = Flask(__name__)
# Create a logger
logger = logging.Client().logger('my-log')
@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
logger.log_text(f"Fetching sessions with category {category}")
sessions_by_category = [session for session in sessions.sessions if category in session['categories']]
logger.log_text(f'Found {len(sessions_by_category)} sessions with category {category}')
return jsonify(sessions_by_category)
# # Other App Routes
أعِد نشر الخدمة على Cloud Run باستخدام الأمر نفسه كما في القسم السابق، وبعد نشرها، نفِّذ بعض الطلبات إلى نقطة النهاية /sessions/categories/<category>.
انتقِل إلى Cloud Console → Logs Explorer

...وستتمكّن من فلترة بيانات تسجيل الدخول هذه كما هو موضّح أدناه:

يمكنك النقر على أي من عبارات السجلّ وتوسيعها، ثم النقر على Explain this log entry، ما سيؤدي إلى استخدام Gemini لشرح إدخال في السجلّ. يُرجى العِلم أنّه إذا لم تفعّل "Gemini في Google Cloud"، سيُطلب منك تفعيل Cloud AI Companion API. يُرجى المتابعة وإجراء ذلك حسب التعليمات.
في ما يلي نموذج إجابة:

16. تهانينا
تهانينا، لقد أنشأت تطبيقًا بنجاح من البداية واستخدمت Gemini Code Assist في جوانب متعددة من دورة حياة تطوير البرامج (SDLC)، بما في ذلك التصميم والإنشاء والاختبار والنشر.
ما هي الخطوات التالية؟
اطّلِع على بعض دروس الترميز التطبيقية هذه...
- جولة في "Duet AI للمطوّرين"
- استخدام Duet AI في جميع مراحل دورة حياة تطوير البرامج
- استخدام Duet AI للمطوّرين لتنسيق الرموز