โมดูล 1: ย้ายข้อมูลจาก Webapp2 ของ App Engine ไปยัง Flask

1. ภาพรวม

Codelab ชุดนี้ (บทแนะนำที่เรียนรู้ได้ด้วยตนเอง) มีเป้าหมายเพื่อช่วยนักพัฒนา Google App Engine (มาตรฐาน) ปรับปรุงแอปให้ทันสมัย โดยแนะนำขั้นตอนการย้ายข้อมูลหลายครั้ง ขั้นตอนที่สำคัญที่สุดคือการเลิกใช้งานบริการแพ็กเกจรันไทม์ต้นฉบับ เนื่องจากรันไทม์รุ่นถัดไปมีความยืดหยุ่นมากกว่า ทำให้ผู้ใช้มีตัวเลือกบริการที่หลากหลายมากขึ้น การเปลี่ยนไปใช้รันไทม์รุ่นใหม่ช่วยให้คุณผสานรวมกับผลิตภัณฑ์ Google Cloud ได้ง่ายขึ้น ใช้บริการที่รองรับได้หลากหลายมากขึ้น และรองรับเวอร์ชันภาษาปัจจุบัน

บทแนะนำเริ่มต้นนี้แสดงขั้นตอนการย้ายข้อมูลขั้นแรกสำหรับการปรับเว็บเฟรมเวิร์กในแอป App Engine ให้ทันสมัย ซึ่งก็คือการย้ายจาก webapp2 ไปยัง Flask ในแอป คุณสามารถใช้เว็บเฟรมเวิร์กใดก็ได้ที่จัดการการกำหนดเส้นทาง แต่สำหรับบทแนะนำนี้ เราใช้ Flask เนื่องจากชุมชนมีการใช้งานอย่างแพร่หลาย

คุณจะได้เรียนรู้วิธีการ

  • ใช้ไลบรารีของบุคคลที่สาม (ในตัวหรืออื่นๆ)
  • อัปเดตไฟล์การกำหนดค่า
  • ย้ายข้อมูลแอปง่ายๆ จาก webapp2 ไปยัง Flask

สิ่งที่คุณต้องมี

แบบสำรวจ

คุณจะใช้ Codelab นี้อย่างไร

โปรดอ่านเท่านั้น อ่านและทำแบบฝึกหัด

2. ข้อมูลเบื้องต้น

เราได้รวมเฟรมเวิร์ก webapp ไว้แล้วเมื่อ App Engine เปิดตัวบน Python 2.5 เป็นครั้งแรกในปี 2008 หลังจากนั้นหลายปีต่อมาก็ได้มี webapp2 เข้ามาแทนที่เมื่อเลิกใช้งานรันไทม์ 2.7 ในปี 2013

แม้ว่า webapp2 (ดูเอกสาร) จะยังอยู่และใช้นอก App Engine เป็นเฟรมเวิร์กเว็บที่เป็นไปตามข้อกำหนด WSGI ได้ แต่ก็ไม่มีการกำหนดเส้นทางคำขอของผู้ใช้ไปยังโค้ดที่เหมาะสมในแอปพลิเคชันของตนเอง แต่ต้องอาศัย App Engine, ไฟล์การกำหนดค่า และนักพัฒนาซอฟต์แวร์ในการกำหนดเส้นทางการรับส่งข้อมูลเว็บไปยัง "แฮนเดิล" ที่ตรงกัน นอกจากนี้ สิทธิประโยชน์หลักของ webapp2 ยังเชื่อมโยงกับบริการแบบแพ็กเกจของ App Engine อย่างไม่มีที่สิ้นสุด แม้ว่าจะใช้งานได้ใน Python 3 ก็ตาม (โปรดดูปัญหาที่เกี่ยวข้องด้วย)

โมดูลนี้ให้ประสบการณ์จริงแก่ผู้ปฏิบัติงานในการย้ายข้อมูลแอป webapp2 แบบง่ายไปยัง Flask ซึ่งเป็นเฟรมเวิร์กที่ App Engine รองรับและบริการอื่นๆ อีกมากมายที่อยู่นอก Google Cloud ทำให้แอปพกพาสะดวกขึ้นมาก หาก Flask ไม่ใช่เฟรมเวิร์กที่ต้องการย้ายแอปพลิเคชันของคุณไป คุณอาจเลือกเฟรมเวิร์กอื่นตราบใดที่แอปมีการกำหนดเส้นทางของตัวเอง Codelab นี้จะแสดงผู้มีอำนาจตัดสินใจด้านเทคโนโลยีสารสนเทศ (ITDM) และนักพัฒนาซอฟต์แวร์เกี่ยวกับขั้นตอนการย้ายข้อมูล เพื่อให้คุณทำความคุ้นเคยกับกระบวนการนี้ได้ไม่ว่าจะย้ายข้อมูลไปในเฟรมเวิร์กใดก็ตาม

ขั้นตอนหลักในการย้ายข้อมูลมีดังนี้

  1. การตั้งค่า/งานล่วงหน้า
  2. เพิ่มไลบรารีของบุคคลที่สามของ Flask
  3. อัปเดตไฟล์แอปพลิเคชัน
  4. อัปเดตไฟล์เทมเพลต HTML

3. การตั้งค่า/งานล่วงหน้า

ก่อนจะไปยังส่วนหลักของบทแนะนำ เราจะตั้งค่าโปรเจ็กต์ รับโค้ด จากนั้นทำความคุ้นเคยกับคำสั่ง gcloud และปรับใช้แอปพื้นฐานเพื่อให้เรารู้ว่าเราเริ่มจากโค้ดที่ใช้งานได้

1. สร้างโปรเจ็กต์

ในฐานะนักพัฒนาซอฟต์แวร์ปัจจุบัน หน้าแดชบอร์ดของ App Engine มีแนวโน้มที่จะแสดงบริการที่คุณใช้อยู่แล้ว เพื่อให้เป็นไปตามวัตถุประสงค์ของบทแนะนำนี้ เราขอแนะนำให้คุณสร้างโปรเจ็กต์ใหม่ หรือใช้โปรเจ็กต์ที่มีอยู่สำหรับบทแนะนำนี้ ตรวจสอบว่าโปรเจ็กต์มีบัญชีสำหรับการเรียกเก็บเงินที่ใช้งานอยู่และเปิดใช้ App Engine (แอป) แล้ว

2. ดาวน์โหลดแอปพื้นฐานตัวอย่าง

ที่เก็บการย้ายข้อมูลของ GAE มีโค้ดทั้งหมดที่คุณต้องการ โคลนหรือดาวน์โหลดไฟล์ ZIP สำหรับบทแนะนำนี้ คุณจะเริ่มต้นด้วยโค้ดในโฟลเดอร์โมดูล 0 (START) และเมื่อคุณดูบทแนะนำเรียบร้อยแล้ว โค้ดของคุณควรตรงกับโฟลเดอร์โมดูล 1 (FINISH) ถ้ายังไม่ได้ตรวจ ให้ตรวจดูความแตกต่างเพื่อให้คุณสามารถดำเนินการในห้องทดลองถัดไป

โฟลเดอร์โมดูล 0 ควรมีไฟล์ที่มีลักษณะเช่นนี้ ดังที่แสดงในคำสั่ง ls POSIX

$ ls
app.yaml        index.html      main.py

3. ทำความคุ้นเคยกับคำสั่ง gcloud

หากยังไม่มีคำสั่ง gcloud ในเครื่อง ให้ติดตั้ง Google Cloud SDK และตรวจสอบว่า gcloud พร้อมใช้งานเป็นส่วนหนึ่งของเส้นทางการดำเนินการและทำความคุ้นเคยกับคำสั่ง gcloud ต่อไปนี้

  1. gcloud components update — อัปเดต Google Cloud SDK
  2. gcloud auth login — เข้าสู่ระบบบัญชีเข้าสู่ระบบ
  3. gcloud config list — แสดงรายการการตั้งค่าการกำหนดค่าโปรเจ็กต์ GCP
  4. gcloud config set project PROJECT_ID — ตั้งค่ารหัสโปรเจ็กต์ GCP
  5. gcloud app deploy — ทำให้แอปพลิเคชัน App Engine ใช้งานได้

หากคุณไม่ได้พัฒนา App Engine กับ gcloud เมื่อเร็วๆ นี้ คุณควรเรียกใช้คำสั่ง 4 รายการแรก (#1-#4) เพื่อตั้งค่าก่อนที่จะไปยังขั้นตอนถัดไป มาดูภาพรวมคร่าวๆ ของคำสั่งเหล่านี้กัน

ก่อนอื่น gcloud components update จะตรวจสอบว่าคุณมี Cloud SDK เวอร์ชันล่าสุด การเรียกใช้คำสั่งนี้ควรได้เอาต์พุตดังนี้

$ gcloud components update

Your current Cloud SDK version is: 317.0.0
You will be upgraded to version: 318.0.0

┌──────────────────────────────────────────────────┐
│        These components will be updated.         │
├──────────────────────────┬────────────┬──────────┤
│           Name           │  Version   │   Size   │
├──────────────────────────┼────────────┼──────────┤
│ Cloud SDK Core Libraries │ 2020.11.06 │ 15.5 MiB │
│ gcloud cli dependencies  │ 2020.11.06 │ 10.6 MiB │
└──────────────────────────┴────────────┴──────────┘

The following release notes are new in this upgrade.
Please read carefully for information about new features, breaking changes,
and bugs fixed.  The latest full release notes can be viewed at:
  https://cloud.google.com/sdk/release_notes

318.0.0 (2020-11-10)

      . . .
      (release notes)
      . . .

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce.

Do you want to continue (Y/n)?

╔════════════════════════════════════════════════════════════╗
╠═ Creating update staging area                             ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: Cloud SDK Core Libraries                   ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: gcloud cli dependencies                    ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: Cloud SDK Core Libraries                     ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: gcloud cli dependencies                      ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Creating backup and activating new installation          ═╣
╚════════════════════════════════════════════════════════════╝

Performing post processing steps...done.

Update done!

To revert your SDK to the previously installed version, you may run:
  $ gcloud components update --version 317.0.0

ต่อไป ให้ใช้ gcloud auth login เพื่อตรวจสอบสิทธิ์ตัวเองสำหรับคำสั่ง gcloud ที่คุณจะออกตั้งแต่นี้เป็นต้นไป

$ gcloud auth login
Your browser has been opened to visit:

    https://accounts.google.com/o/oauth2/auth?response_type=code&client_id= . . .

You are now logged in as [YOUR_EMAIL].
Your current project is [PROJECT_ID].  You can change this setting by running:
  $ gcloud config set project PROJECT_ID

ใช้ gcloud config list เพื่อดูการตั้งค่าโปรเจ็กต์ปัจจุบันของคุณ:

$ gcloud config list
[core]
account = YOUR_EMAIL
disable_usage_reporting = False
project = PROJECT_ID

Your active configuration is: [default]

คำสั่งด้านบนควรแนะนำคุณในการสร้างโปรเจ็กต์ใหม่หรือเลือกโปรเจ็กต์ที่มีอยู่ หากเอาต์พุตของ gcloud config list ไม่ตรงกับโปรเจ็กต์ที่เลือกซึ่งคุณตั้งใจจะใช้สำหรับบทแนะนำนี้ ให้เรียกใช้ gcloud config set project PROJECT_ID เพื่อตั้งค่ารหัสโปรเจ็กต์ จากนั้นตรวจสอบว่าได้ตั้งค่ารหัสโปรเจ็กต์ที่ถูกต้องแล้วโดยการเรียกใช้ gcloud config list อีกครั้ง

$ gcloud config set project PROJECT_ID
Updated property [core/project].

หากต้องการใช้ Cloud Console แทน คุณสามารถทำตามอินเทอร์เฟซผู้ใช้เพื่อสร้างโปรเจ็กต์ใหม่ได้หากต้องการ หรือใช้โปรเจ็กต์ที่มีอยู่ก่อนแล้ว บนหน้าแดชบอร์ดของโปรเจ็กต์ คุณควรจะเห็นการ์ดข้อมูลโปรเจ็กต์ซึ่งแสดงรหัส (พร้อมชื่อและหมายเลขโปรเจ็กต์)

การ์ดข้อมูลโครงการ

คำสั่งสุดท้าย (#5) gcloud app deploy คือการทำให้แอปใช้งานได้ใน App Engine เนื่องจากเราเพิ่งเริ่มต้น ดังนั้นการเรียกใช้งานตอนนี้จึงไม่บังคับ แต่เราจะไม่ไม่สนับสนุนการทำให้โค้ดโมดูล 0 ใช้งานได้เพื่อยืนยันว่าโค้ดใช้งานได้ ขณะดำเนินการ ให้เลือกภูมิภาคทางภูมิศาสตร์ที่คุณต้องการให้แอปทำงาน (โดยปกติจะเป็นสถานที่ที่คุณอยู่) แต่จะเปลี่ยนไม่ได้เมื่อตั้งค่าแล้ว จากนั้นชมข้อมูลการทำให้ใช้งานได้ที่เหลือ เมื่อการตรวจสอบเสร็จสิ้น คุณจะได้รับแจ้งเกี่ยวกับ URL สำหรับการให้บริการแอปของคุณ นี่คือข้อมูลสรุปเกี่ยวกับสิ่งที่คุณอาจเห็น

$ gcloud app deploy
Services to deploy:

descriptor:      [/private/tmp/mod0-baseline/app.yaml]
source:          [/private/tmp/mod0-baseline]
target project:  [PROJECT_ID]
target service:  [default]
target version:  [20201116t220827]
target url:      [https://PROJECT_ID.REG_ABBR.r.appspot.com]


Do you want to continue (Y/n)?

Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 1 file to Google Cloud Storage                 ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://PROJECT_ID.REG_ABBR.r.appspot.com]

You can stream logs from the command line by running:
  $ gcloud app logs tail -s default

To view your application in the web browser run:
  $ gcloud app browse

หากไม่ได้ใช้ App Engine มาระยะหนึ่งแล้ว คุณอาจสังเกตเห็นว่าคำสั่ง appcfg.py update การทำให้ใช้งานได้ดั้งเดิมได้รับการแทนที่โดย gcloud app deploy ดูข้อมูลเพิ่มเติมเกี่ยวกับ gcloud app deploy ได้ที่หน้าเอกสารประกอบ

การเปลี่ยนแปลงล่าสุดอีกอย่างคือ แก้ไข URL จาก http://PROJECT_ID.appspot.com เป็น http://PROJECT_ID.REG_ABBR.r.appspot.com แอปส่วนใหญ่จะแปลงเป็นรูปแบบใหม่ในท้ายที่สุด ดูข้อมูลเพิ่มเติมเกี่ยวกับรูปแบบ URL ได้ในเอกสารประกอบเกี่ยวกับคําขอและการกำหนดเส้นทาง

หลังจากทำให้แอปใช้งานได้แล้ว ให้รีเฟรชเบราว์เซอร์ (อาจ 2-3 ครั้ง) เพื่อดูการเข้าชมล่าสุด

แอปvisitme

หากแอปเป็นแอปใหม่ คุณจะเห็นการเข้าชมเพียง 1 ครั้งหรือ 2-3 ครั้งเท่านั้น

4. เพิ่มไลบรารีของบุคคลที่สามของ Flask

รันไทม์ของ Python 2 App Engine มีชุด "ในตัว" ไลบรารีของบุคคลที่สามที่คุณต้องทำก็แค่ระบุไลบรารีดังกล่าวในไฟล์ app.yaml เพื่อใช้งาน แม้ว่าการย้ายข้อมูลนี้จะไม่จำเป็นต้องใช้ผู้ใช้ แต่การย้ายข้อมูลจะอยู่ในบทแนะนำการย้ายข้อมูลครั้งถัดไป (สำหรับโมดูล 2)

ต้องระบุไลบรารีของบุคคลที่สามที่ไม่มีในตัวไว้ในไฟล์ชื่อ requirements.txt และติดตั้งไว้ในโฟลเดอร์ lib ในไดเรกทอรีเดียวกันกับโค้ดของแอปพลิเคชันที่มีการอัปโหลดทุกอย่างไปยัง App Engine เอกสารประกอบเกี่ยวกับการรวมกลุ่มไลบรารีของบุคคลที่สามมีข้อมูลเพิ่มเติม

ไลบรารีที่คัดลอก เช่น Flask กำหนดให้คุณต้องแจ้งให้ App Engine ค้นหาไลบรารีเหล่านั้นในโฟลเดอร์ lib โดยใช้ไฟล์การกำหนดค่า appengine_config.py ไฟล์การกำหนดค่า appengine_config.py อยู่ในโฟลเดอร์แอปพลิเคชันระดับบนสุดเดียวกับ requirements.txt และ lib ในส่วนนี้ คุณจะทำสิ่งต่อไปนี้ได้

  • สร้าง requirements.txt (ระบุไลบรารีของบุคคลที่สามที่คัดลอก [ไม่มีในตัว])
  • สร้าง appengine_config.py (รู้จักไลบรารีของบุคคลที่สาม)
  • ติดตั้งแพ็กเกจ (บุคคลที่สาม) และทรัพยากร Dependency

1. สร้างrequirements.txt

สร้างไฟล์ requirements.txt เพื่อระบุแพ็กเกจ ในกรณีของเรา Flask คือไลบรารีของบุคคลที่สามที่จำเป็นต้องมี ในช่วงเวลาที่เขียนนี้ เวอร์ชันล่าสุดคือ 1.1.2 ดังนั้น โปรดสร้าง requirements.txt ด้วยบรรทัดเดียวนี้:

Flask==1.1.2

ดูข้อมูลเพิ่มเติมเกี่ยวกับรูปแบบที่ยอมรับได้จากเอกสารประกอบ requirements.txt

2. สร้างappengine_config.py

ขั้นตอนถัดไปคือให้ App Engine รู้จักไลบรารีของบุคคลที่สามภายนอก สร้างไฟล์ชื่อ appengine_config.py ด้วยเนื้อหาต่อไปนี้

from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)

โค้ดนี้จะทำงานตามที่เราระบุไว้ก่อนหน้านี้ กล่าวคือ ชี้ App Engine ไปยังโฟลเดอร์ lib สำหรับไลบรารีที่คัดลอก

3. ติดตั้งแพ็กเกจและทรัพยากร Dependency

ตอนนี้ให้เรียกใช้คำสั่ง pip install เพื่อสร้างโฟลเดอร์ lib และติดตั้ง Flask และทรัพยากร Dependency ในโฟลเดอร์ดังกล่าว

$ pip install -t lib -r requirements.txt

ไม่ว่าจะใช้ pip หรือ pip2 หลังจากติดตั้งแพ็กเกจเสร็จแล้ว คุณควรมีโฟลเดอร์ lib ซึ่งมีเนื้อหาคล้ายกับต่อไปนี้

$ ls lib
bin/
click/
click-7.1.2.dist-info/
flask/
Flask-1.1.2.dist-info/
itsdangerous/
itsdangerous-1.1.0.dist-info/
jinja2/
Jinja2-2.11.2.dist-info/
markupsafe/
MarkupSafe-1.1.1.dist-info/
werkzeug/
Werkzeug-1.0.1.dist-info/

5. อัปเดตไฟล์แอปพลิเคชัน

ตอนนี้เรามาอัปเดตไฟล์แอปพลิเคชัน main.py กัน

1. การนำเข้า

ระบบจะนำเข้าก่อนเช่นเดียวกับในไฟล์ Python ทั้งหมด ตามด้วยการนำเข้าเฟรมเวิร์ก webapp2 ตามด้วยไลบรารีของ Datastore ของ ndb และสุดท้ายคือส่วนขยาย App Engine ที่ประมวลผลเทมเพลตสไตล์ Django คุณควรจะเห็นสิ่งต่อไปนี้

  • ก่อน:
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template

เมื่อย้ายไปยัง Flask คุณจะนำเข้าทั้ง Flask และชิ้นส่วนแสดงภาพเทมเพลตพร้อมกัน ลบคู่การนำเข้าที่เกี่ยวข้องกับ webapp2 แล้วแทนที่ดังนี้ (ปล่อยการนำเข้า ndb ไว้ตามเดิม)

  • หลัง:
from flask import Flask, render_template, request
from google.appengine.ext import ndb

2. เริ่มต้นทำงาน

แอปที่ใช้ webapp2 ต้องการอาร์เรย์เดียว (รายการ Python) ที่แสดงเส้นทางและเครื่องจัดการทั้งหมดในไฟล์ Python (อาจมีรายการอื่นๆ) ดังนี้

  • ก่อน:
app = webapp2.WSGIApplication([
    ('/', MainHandler),
], debug=True)

โปรดทราบว่า app.yaml จะทำการกำหนดเส้นทางในระดับที่สูงกว่าและอาจเรียกใช้ตัวแฮนเดิลอื่นๆ แอปตัวอย่างใช้งานง่ายพอที่จะทำให้เส้นทางทั้งหมดมาที่เครื่องจัดการ main.py

Flask ไม่ได้ใช้ตารางกำหนดเส้นทางลักษณะนี้ ดังนั้นโปรดลบบรรทัดเหล่านี้ใน main.py Flask ต้องมีการเริ่มต้นเช่นกัน ดังนั้นให้เพิ่มบรรทัดต่อไปนี้ที่ด้านบนของ main.py ใต้การนำเข้า

  • หลัง:
app = Flask(__name__)

ใน Flask ให้คุณเริ่มต้นเฟรมเวิร์กแล้วใช้การตกแต่งเพื่อกำหนดเส้นทาง นอกจากนี้ เส้นทางจะจับคู่กับฟังก์ชัน ไม่ใช่คลาสหรือเมธอด

การรวมบทแนะนำ Flask ไว้ใน Codelab นี้อยู่นอกขอบเขต ดังนั้นให้สละเวลาศึกษาบทแนะนำ Flask และอ่านเอกสาร Flask เพื่อทำความคุ้นเคยกับเฟรมเวิร์ก

3. โมเดลข้อมูล

ไม่มีการเปลี่ยนแปลงที่นี่ พื้นที่เก็บข้อมูลจะเป็นหัวใจสำคัญของ Codelab ถัดไป

4. ตัวจัดการ

แอปพลิเคชัน ไม่ว่าคุณจะใช้เฟรมเวิร์กใด (webapp2 หรือ Flask) จะทำ 3 สิ่งต่อไปนี้ได้

  1. จัดการคำขอ GET เส้นทางรูท (/)
  2. ลงทะเบียนหน้าเว็บ "การเข้าชม" (สร้าง/จัดเก็บออบเจ็กต์ Visit รายการ)
  3. แสดงการเข้าชมล่าสุด 10 อันดับแรก (ด้วยเทมเพลตที่กำหนดไว้ล่วงหน้า index.html)

เฟรมเวิร์ก webapp2 ใช้รูปแบบการดำเนินการตามคลาสซึ่งสร้างตัวแฮนเดิลสำหรับเมธอด HTTP ที่รองรับแต่ละเมธอด ในกรณีง่ายๆ เรามีเพียง GET เท่านั้น ดังนั้น จึงมีการกำหนดเมธอด get() ดังนี้

  • ก่อน:
class MainHandler(webapp2.RequestHandler):
    def get(self):
        store_visit(self.request.remote_addr, self.request.user_agent)
        visits = fetch_visits(10) or ()  # empty sequence if None
        tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(tmpl, {'visits': visits}))

ดังที่กล่าวไว้ข้างต้น Flask ดำเนินการกำหนดเส้นทางของตัวเอง คุณจะเขียนฟังก์ชันและตกแต่งฟังก์ชันด้วยเส้นทางที่เรียกใช้แทนคลาสของเครื่องจัดการ ผู้ใช้สามารถระบุเมธอด HTTP ที่จัดการในการเรียกใช้ตัวตกแต่งได้ เช่น @app.route('/app/', methods=['GET', 'POST']) เนื่องจากค่าเริ่มต้นคือ GET เท่านั้น (โดยปริยายคือ HEAD) จึงสามารถปิดไว้ได้

ในการย้ายข้อมูลไปยัง Flask ให้แทนที่คลาส MainHandler และเมธอด get() ด้วยฟังก์ชันการกำหนดเส้นทาง Flask ต่อไปนี้

  • หลัง:
@app.route('/')
def root():
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10) or ()  # empty sequence if None
    return render_template('index.html', visits=visits)

แน่นอนว่านี่ไม่ใช่ตัวแทนของแอปซึ่งจะต้องซับซ้อนกว่าตัวอย่างนี้ เป้าหมายหลักอย่างหนึ่งของบทแนะนำเหล่านี้คือการช่วยคุณเริ่มต้น สร้าง "ความจำกล้ามเนื้อ" และทำความเข้าใจตำแหน่งที่ต้องทำการเปลี่ยนแปลงในโค้ดสำหรับ App Engine โดยเฉพาะ เพื่อยืนยันว่าคุณได้ทำการเปลี่ยนแปลงนี้อย่างถูกต้อง ให้เปรียบเทียบการเปลี่ยนแปลงของคุณกับโมดูล 1 main.py

5. ไฟล์เสริม

ไม่มีการเปลี่ยนแปลงในไฟล์ .gcloudignore วัตถุประสงค์ของหน้านี้คือการระบุไฟล์ที่ไม่ทำให้ App Engine ใช้งานได้และไม่จำเป็นต่อการทำให้แอปพลิเคชันใช้งานได้ ซึ่งรวมถึงแต่ไม่จำกัดเพียง Python เสริม การควบคุมแหล่งที่มา ที่เก็บต้นแบบ และไฟล์อื่นๆ .gcloudignore ของเราจะมีลักษณะดังนี้ (โดยนำความคิดเห็นออกเพื่อความสั้นกระชับ)

.gcloudignore
.git
.gitignore
.hgignore
.hg/
*.pyc
*.pyo
__pycache__/
/setup.cfg
README.md

6. อัปเดตไฟล์เทมเพลต HTML

1. ย้ายไฟล์เทมเพลต

ในโฟลเดอร์ที่เก็บพื้นฐาน (โมดูล 0) ไฟล์เทมเพลต index.html จะอยู่ในโฟลเดอร์เดียวกับไฟล์แอปพลิเคชัน เนื่องจาก Flask ต้องใช้ไฟล์ HTML ที่อยู่ในโฟลเดอร์ templates คุณจึงต้องสร้างโฟลเดอร์ดังกล่าว (mkdir templates) และย้าย index.html ไปไว้ที่นั่น ในระบบที่รองรับ POSIX เช่น Linux หรือ Mac OS X คำสั่งจะเป็นดังนี้

mkdir templates
mv index.html templates

2. อัปเดตไฟล์เทมเพลต

เมื่อย้าย index.html ไปยัง templates แล้ว ก็ถึงเวลาทำการแก้ไขเล็กน้อยแต่ต้องทำ เรามาลองดูไฟล์เทมเพลตต้นฉบับอย่างละเอียดกัน

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

</body>
</html>

ขณะที่ webapp2 ใช้เทมเพลต Django ซึ่งเรียกใช้ Callable เช่น visit.timestamp.ctime โดยไม่มีวงเล็บ ( ) แต่ Jinja2 ต้องใช้เทมเพลตนี้อย่างชัดเจน แม้ว่าจะดูเหมือนเป็นการปรับแต่งเล็กน้อย แต่เทมเพลต Jinja มีประสิทธิภาพมากกว่าที่พร้อมใช้งานทันทีเนื่องจากคุณสามารถส่งต่ออาร์กิวเมนต์ในการโทรได้

ใน Django คุณต้องสร้าง "แท็กเทมเพลต" หรือเขียนฟิลเตอร์ เมื่อทำความเข้าใจเรื่องนี้แล้ว ให้อัปเดต index.html ด้วยการเพิ่มวงเล็บในการเรียก visit.timestamp.ctime:

  • ก่อน:
<li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
  • หลัง:
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>

นี่คือการเปลี่ยนแปลงเพียงอย่างเดียวที่จำเป็น ไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ กับ index.html กับ Codelab ของการย้ายข้อมูลที่เหลือทั้งหมด

7. สรุป/ล้างข้อมูล

ทำให้แอปพลิเคชันใช้งานได้

เมื่อคุณทำการเปลี่ยนแปลงทั้งหมดในบทแนะนำนี้เสร็จแล้ว ไฟล์ในโฟลเดอร์แอปพลิเคชันควรเหมือนกัน (หรือเกือบเหมือน) กับไฟล์ในโฟลเดอร์ที่เก็บโมดูล 1 เพียงทำให้ใช้งานได้ตอนนี้ และดูว่าแอปพลิเคชัน Module 1 Flask จะทำงานเหมือนกับเวอร์ชันโมดูล 0 webapp2

ใช้คำสั่ง gcloud app deploy เหมือนที่เราทำก่อนหน้านี้เมื่อทำให้โค้ดโมดูล 0 เดิมใช้งานได้ การเข้าถึงแอปที่ PROJECT_ID.appspot.com ไม่ว่าจะจากเว็บเบราว์เซอร์หรือคำสั่ง curl หรือ wget เพื่อยืนยันว่าแอปทำงานตามที่คาดหมาย

หากคุณได้รับข้อผิดพลาดเกี่ยวกับเซิร์ฟเวอร์ โดยทั่วไปหมายความว่ามีการพิมพ์ผิดในโค้ด Python ตรวจสอบบันทึกแอปพลิเคชันของคุณเพื่อตรวจสอบ จากนั้นเปรียบเทียบไฟล์ของคุณกับไฟล์ในที่เก็บโมดูล 1 (ลิงก์ด้านบน)

ไม่บังคับ: ล้างข้อมูล

จะต้องทำอย่างไรเพื่อหลีกเลี่ยงการเรียกเก็บเงินจนกว่าคุณจะพร้อมสำหรับการย้ายข้อมูลไปยัง Codelab ครั้งถัดไป ในฐานะนักพัฒนาซอฟต์แวร์ปัจจุบัน คุณมีแนวโน้มที่จะติดตามข้อมูลราคาของ App Engine ได้อย่างทันท่วงที

ไม่บังคับ: ปิดใช้แอป

หากยังไม่พร้อมดูบทแนะนำถัดไป ให้ปิดใช้แอปเพื่อหลีกเลี่ยงการเรียกเก็บเงิน เมื่อพร้อมที่จะไปยัง Codelab ถัดไปแล้ว คุณก็เปิดใช้อีกครั้งได้ ระหว่างที่แอปปิดใช้อยู่ แอปจะไม่ทำให้เกิดการเรียกเก็บเงินใดๆ แต่อาจมีการเรียกเก็บเงินอีกอย่างหนึ่งคือการใช้พื้นที่เก็บข้อมูล หากแอปเกินโควต้าฟรี ให้ลบให้ไม่เกินจำนวนที่จำกัดไว้

ในทางกลับกัน หากไม่ต้องการย้ายข้อมูลต่อและต้องการลบทุกอย่างออกทั้งหมด คุณปิดโปรเจ็กต์ได้

ขั้นตอนถัดไป

มีโมดูลการย้ายข้อมูล 2 รายการที่เริ่มต้นด้วยโค้ดโมดูล 1 ที่เสร็จสมบูรณ์ โมดูล 2 และ 7 ดังนี้

  • โมดูล 2 (จำเป็นหากใช้ Datastore)
    • ย้ายข้อมูลจาก App Engine ndb ไปยัง Cloud NDB
    • หลังจากเปลี่ยนไปใช้ Cloud NDB แล้ว จะมีตัวเลือกอื่นๆ อีกมากมาย
      • คอนเทนเนอร์แอปเพื่อให้ทำงานใน Cloud Run
      • การย้ายข้อมูลแอปไปยังไลบรารีของไคลเอ็นต์ Cloud Datastore
      • การย้ายข้อมูลแอปไปยัง Cloud Firestore เพื่อเข้าถึงฟีเจอร์ของ Firebase
  • โมดูล 7 (ต้องระบุหากใช้คิวงาน [push])
    • เพิ่มการใช้งาน taskqueue ของ App Engine (ข้อความ Push)
    • เตรียมแอปโมดูล 1 สำหรับการย้ายข้อมูลไปยัง Cloud Tasks ในโมดูล 8

8. แหล่งข้อมูลเพิ่มเติม

ปัญหา/ข้อเสนอแนะเกี่ยวกับ Codelab ของโมดูลการย้ายข้อมูล App Engine

หากมีปัญหาใดๆ เกี่ยวกับ Codelab นี้ โปรดค้นหาปัญหาของคุณก่อนยื่น ลิงก์สำหรับค้นหาและสร้างปัญหาใหม่

ทรัพยากรการย้ายข้อมูล

คุณสามารถดูลิงก์ไปยังโฟลเดอร์ที่เก็บสำหรับโมดูล 0 (START) และโมดูล 1 (FINISH) ได้ในตารางด้านล่าง นอกจากนี้ยังเข้าถึงได้จากที่เก็บข้อมูลสำหรับการย้ายข้อมูล App Engine ทั้งหมด ซึ่งคุณจะโคลนหรือดาวน์โหลดไฟล์ ZIP ได้

Codelab

Python 2

Python 3

โมดูล 0

รหัส

(ไม่มี)

โมดูล 1

รหัส

(ไม่มี)

ทรัพยากร App Engine

ด้านล่างนี้คือแหล่งข้อมูลเพิ่มเติมเกี่ยวกับการย้ายข้อมูลครั้งนี้