نحوه استفاده از App Engine blobstore (ماژول 15)

1. بررسی اجمالی

مجموعه کدهای ایستگاه انتقال بدون سرور (آموزش‌های عملی) و ویدیوهای مرتبط با هدف کمک به توسعه‌دهندگان بدون سرور Google Cloud برای مدرن کردن برنامه‌های خود با هدایت آنها از طریق یک یا چند انتقال، عمدتاً از سرویس‌های قدیمی دور می‌شوند. انجام این کار برنامه های شما را قابل حمل تر می کند و گزینه ها و انعطاف پذیری بیشتری در اختیار شما قرار می دهد و به شما امکان می دهد با طیف وسیع تری از محصولات Cloud ادغام شده و به آنها دسترسی داشته باشید و راحت تر به نسخه های زبان جدیدتر ارتقا دهید. در حالی که در ابتدا بر روی اولین کاربران Cloud، عمدتاً توسعه دهندگان App Engine (محیط استاندارد) تمرکز می شود، این مجموعه به اندازه کافی گسترده است که شامل سایر پلتفرم های بدون سرور مانند Cloud Functions و Cloud Run یا در صورت وجود جاهای دیگر است.

این کد ماژول 15 نحوه افزودن استفاده از App Engine blobstore را به برنامه نمونه از ماژول 0 توضیح می‌دهد. سپس در ماژول 16 آماده انتقال این استفاده به Cloud Storage خواهید بود.

شما یاد خواهید گرفت که چگونه

  • استفاده از App Engine Blobstore API/کتابخانه را اضافه کنید
  • آپلودهای کاربران را در سرویس blobstore ذخیره کنید
  • برای مرحله بعدی مهاجرت به فضای ذخیره سازی ابری آماده شوید

آنچه شما نیاز دارید

نظرسنجی

چگونه از این آموزش استفاده خواهید کرد؟

فقط از طریق آن را بخوانید آن را بخوانید و تمرینات را کامل کنید

تجربه خود را با پایتون چگونه ارزیابی می کنید؟

تازه کار متوسط مسلط

تجربه خود را در استفاده از خدمات Google Cloud چگونه ارزیابی می کنید؟

تازه کار متوسط مسلط

2. پس زمینه

به منظور مهاجرت از App Engine Blobstore API، استفاده از آن را از ماژول 0 به برنامه اصلی App Engine ndb موجود اضافه کنید. برنامه نمونه ده بازدید اخیر کاربر را نشان می دهد. ما در حال تغییر برنامه هستیم تا از کاربر نهایی بخواهد مصنوع (فایلی) را که با "بازدید" آنها مطابقت دارد، آپلود کند. اگر کاربر مایل به انجام این کار نیست، گزینه "پرش" وجود دارد. صرف نظر از تصمیم کاربر، صفحه بعدی همان خروجی برنامه را از ماژول 0 (و بسیاری از ماژول های دیگر در این سری) ارائه می دهد. با اجرای این ادغام blobstore App Engine، می‌توانیم آن را به Cloud Storage در آزمایشگاه کد بعدی (ماژول 16) منتقل کنیم.

App Engine دسترسی به سیستم‌های قالب‌بندی جنگو و Jinja2 را فراهم می‌کند، و چیزی که این مثال را متفاوت می‌کند (علاوه بر اضافه کردن دسترسی Blobstore) این است که از استفاده از جنگو در ماژول 0 به Jinja2 در اینجا در ماژول 15 تغییر می‌کند. یک گام کلیدی در مدرن کردن App Engine برنامه ها برای انتقال چارچوب های وب از webapp2 به Flask است. دومی از Jinja2 به عنوان سیستم قالب پیش‌فرض خود استفاده می‌کند، بنابراین با پیاده‌سازی Jinja2 در حالی که در webapp2 برای دسترسی Blobstore می‌مانیم، حرکت در آن جهت را آغاز می‌کنیم. از آنجایی که Flask به طور پیش‌فرض از Jinja2 استفاده می‌کند، این بدان معناست که هیچ تغییری در قالب در ماژول 16 مورد نیاز نخواهد بود.

3. راه اندازی/پیش کار

قبل از اینکه به بخش اصلی آموزش برسیم، پروژه خود را راه اندازی کنید، کد را دریافت کنید و برنامه پایه را برای شروع با کد کار اجرا کنید.

1. پروژه راه اندازی

اگر قبلاً برنامه Module 0 را مستقر کرده اید، توصیه می کنیم از همان پروژه (و کد) دوباره استفاده کنید. از طرف دیگر، می توانید یک پروژه کاملاً جدید ایجاد کنید یا از پروژه موجود دیگری استفاده مجدد کنید. مطمئن شوید که پروژه دارای حساب صورتحساب فعال است و App Engine فعال است.

2. برنامه نمونه پایه را دریافت کنید

یکی از پیش نیازهای این نرم افزار کد، داشتن یک برنامه نمونه کار با ماژول 0 است. اگر آن را ندارید، می توانید آن را از پوشه "START" ماژول 0 (لینک زیر) دریافت کنید. این لبه کد شما را در هر مرحله راهنمایی می کند و با کدی که شبیه آنچه در پوشه "FINISH" ماژول 15 است به پایان می رسد.

دایرکتوری فایل های شروع ماژول 0 باید به شکل زیر باشد:

$ ls
README.md               index.html
app.yaml                main.py

3. (دوباره) استقرار برنامه پایه

مراحل پیش‌کار باقی‌مانده برای اجرا اکنون:

  1. دوباره با ابزار خط فرمان gcloud آشنا شوید
  2. برنامه نمونه را با gcloud app deploy مجدداً مستقر کنید
  3. تأیید کنید که برنامه بدون مشکل در App Engine اجرا می شود

هنگامی که آن مراحل را با موفقیت انجام دادید و مشاهده کردید که برنامه وب شما کار می کند (با خروجی مشابه زیر)، آماده هستید تا استفاده از کش را به برنامه خود اضافه کنید.

a7a9d2b80d706a2b.png

4. فایل های پیکربندی را به روز کنید

app.yaml

هیچ تغییر اساسی در پیکربندی برنامه وجود ندارد، با این حال همانطور که قبلا ذکر شد، ما از قالب جنگو (پیش‌فرض) به Jinja2 حرکت می‌کنیم، بنابراین برای تغییر، کاربران باید آخرین نسخه Jinja2 موجود در سرورهای App Engine را مشخص کنند، و شما این کار را انجام می‌دهید. با افزودن آن به بخش داخلی کتابخانه های شخص ثالث app.yaml .

قبل از:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

فایل app.yaml خود را با افزودن یک بخش libraries جدید مانند آنچه در اینجا می بینید ویرایش کنید:

بعد از:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: jinja2
  version: latest

هیچ فایل پیکربندی دیگری نیاز به به روز رسانی ندارد، بنابراین بیایید به سراغ فایل های برنامه برویم.

5. فایل های برنامه را تغییر دهید

واردات و پشتیبانی Jinja2

اولین مجموعه تغییرات برای main.py شامل اضافه کردن استفاده از Blobstore API و جایگزینی قالب جنگو با Jinja2 است. این چیزی است که در حال تغییر است:

  1. هدف ماژول os ایجاد یک نام مسیر فایل برای قالب جنگو است. از آنجایی که در آنجا به Jinja2 تغییر می‌دهیم، استفاده از os و همچنین ارائه‌دهنده الگوی جنگو، google.appengine.ext.webapp.template ، دیگر مورد نیاز نیست، بنابراین حذف می‌شوند.
  2. API Blobstore را وارد کنید: google.appengine.ext.blobstore
  3. کنترل‌کننده‌های Blobstore موجود در چارچوب اصلی webapp را وارد کنید—آنها در webapp2 در دسترس نیستند: google.appengine.ext.webapp.blobstore_handlers
  4. پشتیبانی Jinja2 را از بسته webapp2_extras وارد کنید

قبل از:

import os
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template

با جایگزین کردن بخش واردات فعلی در main.py با قطعه کد زیر، تغییرات را در لیست بالا اعمال کنید.

بعد از:

import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers

پس از وارد کردن، مقداری کد دیگ بخار برای پشتیبانی از استفاده از Jinja2 همانطور که در webapp2_extras docs تعریف شده است، اضافه کنید. قطعه کد زیر کلاس کنترل کننده درخواست استاندارد webapp2 را با عملکرد Jinja2 می‌پوشاند، بنابراین این بلوک کد را درست بعد از وارد کردن به main.py اضافه کنید:

class BaseHandler(webapp2.RequestHandler):
    'Derived request handler mixing-in Jinja2 support'
    @webapp2.cached_property
    def jinja2(self):
        return jinja2.get_jinja2(app=self.app)

    def render_response(self, _template, **context):
        self.response.write(self.jinja2.render_template(_template, **context))

پشتیبانی Blobstore را اضافه کنید

برخلاف سایر انتقال‌ها در این سری که عملکرد یا خروجی برنامه نمونه را بدون تغییر (بسیار) در UX یکسان (یا تقریباً یکسان) نگه می‌داریم، این مثال یک انحراف اساسی‌تر از هنجار دارد. به جای ثبت فوری یک بازدید جدید و سپس نمایش ده مورد اخیر، ما در حال به روز رسانی برنامه هستیم تا از کاربر یک مصنوع فایل بخواهیم تا بازدید خود را با آن ثبت کند. سپس کاربران نهایی می توانند فایل مربوطه را آپلود کنند یا "Skip" را انتخاب کنند تا اصلاً چیزی آپلود نشود. پس از اتمام این مرحله، صفحه "آخرین بازدیدها" نمایش داده می شود.

این تغییر به برنامه ما اجازه می دهد تا از سرویس Blobstore برای ذخیره (و احتمالاً بعداً رندر) آن تصویر یا نوع فایل دیگر در آخرین صفحه بازدید استفاده کند.

به روز رسانی مدل داده و پیاده سازی استفاده از آن

ما داده‌های بیشتری را ذخیره می‌کنیم، به‌ویژه مدل داده‌ها را برای ذخیره شناسه (به نام " BlobKey ") فایل آپلود شده در Blobstore به‌روزرسانی می‌کنیم و یک مرجع برای ذخیره آن در store_visit() اضافه می‌کنیم. از آنجایی که این داده های اضافی همراه با هر چیز دیگری پس از پرس و جو برگردانده می شود، fetch_visits() یکسان می ماند.

در اینجا قبل و بعد از این به روز رسانی ها با file_blob ، یک ndb.BlobKeyProperty آمده است:

قبل از:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

بعد از:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.BlobKeyProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent),
            file_blob=upload_key).put()

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

در اینجا یک نمایش تصویری از تغییراتی است که تاکنون ایجاد شده است:

2270783776759f7f.png

پشتیبانی از آپلود فایل

مهم‌ترین تغییر در عملکرد، پشتیبانی از آپلود فایل‌ها است، چه درخواست از کاربر برای یک فایل، پشتیبانی از ویژگی «پرش» یا ارائه یک فایل مربوط به یک بازدید. همه اینها بخشی از تصویر است. اینها تغییرات مورد نیاز برای پشتیبانی از آپلود فایل هستند:

  1. درخواست GET کنترل کننده اصلی دیگر آخرین بازدیدها را برای نمایش واکشی نمی کند. در عوض، کاربر را برای آپلود درخواست می کند.
  2. هنگامی که کاربر نهایی فایلی را برای آپلود ارسال می‌کند یا از آن فرآیند رد می‌شود، یک POST از فرم، کنترل را به UploadHandler جدید که از google.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandler مشتق شده است، منتقل می‌کند.
  3. روش POST UploadHandler آپلود را انجام می دهد، برای ثبت بازدید store_visit() را فراخوانی می کند و یک تغییر مسیر HTTP 307 را برای ارسال کاربر به "/"، که در آن...
  4. متد POST کنترل کننده اصلی برای (از طریق fetch_visits() ) پرس و جو می کند و آخرین بازدیدها را نمایش می دهد. اگر کاربر «پرش» را انتخاب کند، هیچ فایلی آپلود نمی‌شود، اما بازدید همچنان ثبت می‌شود و به دنبال آن همان تغییر مسیر انجام می‌شود.
  5. نمایش آخرین بازدیدها شامل یک فیلد جدید است که به کاربر نمایش داده می‌شود، یا در صورت وجود فایل آپلود، "نمایش" پیوند داده شده یا "هیچ" در غیر این صورت. این تغییرات در قالب HTML همراه با افزودن یک فرم آپلود (اطلاعات بیشتر در مورد این به زودی) تحقق می یابد.
  6. اگر کاربر نهایی برای هر بازدیدی با یک ویدیوی آپلود شده، روی پیوند "مشاهده" کلیک کند، یک درخواست GET به ViewBlobHandler جدید، برگرفته از google.appengine.ext.webapp.blobstore_handlers.BlobstoreDownloadHandler ، درخواست می کند، یا اگر یک تصویر باشد، فایل را رندر می کند. (در مرورگر در صورت پشتیبانی)، درخواست دانلود در غیر این صورت، یا بازگشت خطای HTTP 404 اگر یافت نشد.
  7. علاوه بر جفت کلاس های کنترل کننده جدید و همچنین یک جفت مسیر جدید برای ارسال ترافیک به آنها، کنترل کننده اصلی به یک روش POST جدید برای دریافت تغییر مسیر 307 که در بالا توضیح داده شد نیاز دارد.

قبل از این به‌روزرسانی‌ها، برنامه Module 0 فقط دارای یک کنترلر اصلی با روش GET و یک مسیر واحد بود:

قبل از:

class MainHandler(webapp2.RequestHandler):
    'main application (GET) handler'
    def get(self):
        store_visit(self.request.remote_addr, self.request.user_agent)
        visits = fetch_visits(10)
        tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(tmpl, {'visits': visits}))

app = webapp2.WSGIApplication([
    ('/', MainHandler),
], debug=True)

با اجرای آن به‌روزرسانی‌ها، اکنون سه کنترل‌کننده وجود دارد: 1) کنترل کننده آپلود با روش POST ، 2) کنترل کننده دانلود "view blob" با روش GET ، و 3) کنترل کننده اصلی با روش‌های GET و POST . این تغییرات را به گونه‌ای انجام دهید که بقیه برنامه شما اکنون مانند شکل زیر باشد.

بعد از:

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    'Upload blob (POST) handler'
    def post(self):
        uploads = self.get_uploads()
        blob_id = uploads[0].key() if uploads else None
        store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
        self.redirect('/', code=307)

class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
    'view uploaded blob (GET) handler'
    def get(self, blob_key):
        self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)

class MainHandler(BaseHandler):
    'main application (GET/POST) handler'
    def get(self):
        self.render_response('index.html',
                upload_url=blobstore.create_upload_url('/upload'))

    def post(self):
        visits = fetch_visits(10)
        self.render_response('index.html', visits=visits)

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/upload', UploadHandler),
    ('/view/([^/]+)?', ViewBlobHandler),
], debug=True)

چندین تماس کلیدی در این کد وجود دارد که ما به تازگی اضافه کردیم:

  • در MainHandler.get ، یک تماس با blobstore.create_upload_url وجود دارد. این فراخوانی URL فرم POST را ایجاد می‌کند و با کنترل کننده آپلود برای ارسال فایل به Blobstore تماس می‌گیرد.
  • در UploadHandler.post ، یک تماس با blobstore_handlers.BlobstoreUploadHandler.get_uploads وجود دارد. این جادوی واقعی است که فایل را در Blobstore قرار می دهد و یک شناسه منحصر به فرد و ثابت برای آن فایل، BlobKey آن را برمی گرداند.
  • در ViewBlobHandler.get ، فراخوانی blobstore_handlers.BlobstoreDownloadHandler.send با BlobKey یک فایل منجر به واکشی فایل و ارسال آن به مرورگر کاربر نهایی می شود.

این تماس ها بخش عمده ای از دسترسی به ویژگی های اضافه شده به برنامه را نشان می دهد. در اینجا یک نمایش تصویری از دومین و آخرین مجموعه تغییرات به main.py است:

da2960525ac1b90d.png

قالب HTML را به روز کنید

برخی از به‌روزرسانی‌های برنامه اصلی بر رابط کاربری (UI) برنامه تأثیر می‌گذارند، بنابراین تغییرات مربوطه در قالب وب مورد نیاز است، در واقع دو مورد:

  1. یک فرم آپلود فایل با 3 عنصر ورودی لازم است: یک فایل و یک جفت دکمه ارسال برای آپلود فایل و پرش.
  2. آخرین خروجی بازدیدها را با افزودن یک پیوند "نما" برای بازدیدهایی با آپلود فایل مربوطه یا "هیچ" به‌روزرسانی کنید.

قبل از:

<!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>

تغییرات را در لیست بالا برای تشکیل الگوی به روز شده اعمال کنید:

بعد از:

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

<h1>VisitMe example</h1>
{% if upload_url %}

<h3>Welcome... upload a file? (optional)</h3>
<form action="{{ upload_url }}" method="POST" enctype="multipart/form-data">
    <input type="file" name="file"><p></p>
    <input type="submit"> <input type="submit" value="Skip">
</form>

{% else %}

<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime() }}
    <i><code>
    {% if visit.file_blob %}
        (<a href="/view/{{ visit.file_blob }}" target="_blank">view</a>)
    {% else %}
        (none)
    {% endif %}
    </code></i>
    from {{ visit.visitor }}
</li>
{% endfor %}
</ul>

{% endif %}

</body>
</html>

این تصویر به روز رسانی های مورد نیاز برای index.html را نشان می دهد:

8583e975f25aa9e7.png

یکی از آخرین تغییرات این است که Jinja2 الگوهای خود را در یک پوشه templates ترجیح می دهد، بنابراین آن پوشه را ایجاد کنید و index.html را داخل آن منتقل کنید. با این حرکت نهایی، اکنون تمام تغییرات لازم برای افزودن استفاده از Blobstore به برنامه نمونه ماژول 0 را انجام داده اید.

(اختیاری) "بهبود" فضای ذخیره سازی ابری

ذخیره سازی Blobstore در نهایت به خود Cloud Storage تبدیل شد. این بدان معنی است که آپلودهای Blobstore در کنسول Cloud، به ویژه مرورگر Cloud Storage قابل مشاهده هستند. سوال اینجاست که کجاست. پاسخ، سطل پیش‌فرض Cloud Storage برنامه App Engine شما است. نام آن نام دامنه کامل برنامه App Engine شما، PROJECT_ID .appspot.com است. این بسیار راحت است زیرا همه شناسه های پروژه منحصر به فرد هستند، درست است؟

به روز رسانی های انجام شده در برنامه نمونه، فایل های آپلود شده را در آن سطل رها می کند، اما توسعه دهندگان این گزینه را دارند که مکان خاصی را انتخاب کنند. سطل پیش‌فرض از طریق برنامه‌نویسی از طریق google.appengine.api.app_identity.get_default_gcs_bucket_name() قابل دسترسی است، اگر می‌خواهید به این مقدار دسترسی داشته باشید، نیاز به وارد کردن جدید دارد، مثلاً به عنوان پیشوندی برای سازمان‌دهی فایل‌های آپلود شده استفاده کنید. به عنوان مثال، مرتب سازی بر اساس نوع فایل:

f61f7a23a1518705.png

به عنوان مثال، برای پیاده سازی چیزی شبیه به آن برای تصاویر، کدی مانند این به همراه کدهایی خواهید داشت که انواع فایل را برای انتخاب نام سطل مورد نظر بررسی می کند:

ROOT_BUCKET = app_identity.get_default_gcs_bucket_name()
IMAGE_BUCKET = '%s/%s' % (ROOT_BUCKET, 'images')

همچنین تصاویر آپلود شده را با استفاده از ابزاری مانند ماژول کتابخانه استاندارد پایتون imghdr برای تأیید نوع تصویر تأیید می‌کنید. در نهایت، احتمالاً می خواهید در صورت وجود بازیگران بد ، حجم آپلودها را محدود کنید .

بیایید بگوییم تمام کارهایی که انجام شده است. چگونه می توانیم برنامه خود را به روز کنیم تا از تعیین محل ذخیره فایل های آپلود شده پشتیبانی کند؟ نکته کلیدی این است که تماس را با blobstore.create_upload_url در MainHandler.get تغییر دهید تا با افزودن پارامتر gs_bucket_name به این صورت، مکان مورد نظر را در Cloud Storage برای آپلود مشخص کنید:

blobstore.create_upload_url('/upload', gs_bucket_name=IMAGE_BUCKET))

از آنجایی که اگر می‌خواهید مشخص کنید بارگذاری‌ها کجا باید بروند، این یک به‌روزرسانی اختیاری است، بخشی از فایل main.py در مخزن نیست. در عوض، یک جایگزین به نام main-gcs.py برای بررسی شما در مخزن موجود است. به جای استفاده از یک سطل جداگانه "پوشه"، کد موجود در main-gcs.py آپلودها را در سطل "root" ( PROJECT_ID .appspot.com ) ذخیره می کند، درست مانند main.py ، اما داربست مورد نیاز شما را در صورت استخراج فراهم می کند. نمونه را به چیزی بیشتر که در این بخش اشاره شده است. در زیر تصویری از "تفاوت" بین main.py و main-gcs.py آمده است.

256e1ea68241a501.png

6. خلاصه/پاکسازی

این بخش با استقرار برنامه، این کد را جمع‌بندی می‌کند و تأیید می‌کند که آن‌طور که در نظر گرفته شده و در هر خروجی منعکس‌شده کار می‌کند. پس از تأیید اعتبار برنامه، مراحل پاکسازی را انجام دهید و مراحل بعدی را در نظر بگیرید.

استقرار و تأیید برنامه

برنامه خود را با gcloud app deploy مجدداً استقرار دهید و تأیید کنید که برنامه طبق آگهی کار می کند و در تجربه کاربری (UX) با برنامه Module 0 متفاوت است. در حال حاضر دو صفحه مختلف در برنامه شما وجود دارد، اولین مورد درخواست فرم آپلود فایل بازدید است:

f5b5f9f19d8ae978.png از آنجا، کاربران نهایی یا یک فایل را آپلود می کنند و روی "ارسال" کلیک می کنند یا روی "پرش" کلیک می کنند تا چیزی آپلود نشود. در هر صورت، نتیجه آخرین صفحه بازدید است که اکنون با پیوندهای "مشاهده" یا "هیچ" بین مهرهای زمانی بازدید و اطلاعات بازدیدکننده افزوده شده است:

f5ac6b98ee8a34cb.png

برای تکمیل این کد لبه با افزودن استفاده از App Engine Blobstore به برنامه نمونه ماژول 0 تبریک می‌گوییم. اکنون کد شما باید با آنچه در پوشه FINISH (ماژول 15) است مطابقت داشته باشد. جایگزین main-gcs.py نیز در آن پوشه وجود دارد.

پاک کن

ژنرال

اگر فعلاً کارتان تمام شده است، توصیه می‌کنیم برنامه App Engine خود را غیرفعال کنید تا از پرداخت صورت‌حساب جلوگیری کنید. با این حال، اگر می‌خواهید بیشتر آزمایش یا آزمایش کنید، پلتفرم App Engine یک سهمیه رایگان دارد، و تا زمانی که از آن سطح استفاده تجاوز نکنید، هزینه‌ای از شما دریافت نمی‌شود. این برای محاسبه است، اما ممکن است هزینه‌هایی برای خدمات App Engine مربوطه نیز وجود داشته باشد، بنابراین صفحه قیمت آن را برای اطلاعات بیشتر بررسی کنید. اگر این انتقال شامل سایر سرویس‌های Cloud باشد، آن‌ها جداگانه صورت‌حساب می‌شوند. در هر صورت، در صورت وجود، بخش «ویژه این کد آزمایشگاه» را در زیر ببینید.

برای افشای کامل، استقرار در یک پلت فرم محاسباتی بدون سرور Google Cloud مانند App Engine هزینه‌های ساخت و ذخیره‌سازی جزئی را متحمل می‌شود. Cloud Build سهمیه رایگان خودش را دارد و Cloud Storage هم دارد. ذخیره سازی آن تصویر مقداری از آن سهمیه را مصرف می کند. با این حال، ممکن است در منطقه‌ای زندگی کنید که چنین سطح رایگانی ندارد، بنابراین برای به حداقل رساندن هزینه‌های احتمالی از میزان استفاده از فضای ذخیره‌سازی خود آگاه باشید. پوشه‌های خاص Cloud Storage که باید بررسی کنید عبارتند از:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • پیوندهای ذخیره سازی بالا به PROJECT_ID و * LOC * شما بستگی دارد، به عنوان مثال، اگر برنامه شما در ایالات متحده میزبانی می شود، " us ".

از سوی دیگر، اگر نمی‌خواهید با این برنامه یا دیگر کدهای مهاجرت مرتبط ادامه دهید و می‌خواهید همه چیز را به طور کامل حذف کنید، پروژه خود را خاموش کنید .

مخصوص این کد لبه

خدمات لیست شده در زیر منحصر به این کدلب است. برای اطلاعات بیشتر به مستندات هر محصول مراجعه کنید:

مراحل بعدی

انتقال منطقی بعدی که باید در نظر بگیرید در ماژول 16 پوشش داده شده است و به توسعه دهندگان نشان می دهد که چگونه از سرویس App Engine Blobstore به استفاده از کتابخانه سرویس گیرنده Cloud Storage مهاجرت کنند. از مزایای ارتقا می توان به دسترسی به ویژگی های بیشتر Cloud Storage، آشنایی با کتابخانه سرویس گیرنده ای که برای برنامه های خارج از App Engine کار می کند، چه در Google Cloud، دیگر ابرها، و یا حتی در محل، اشاره کرد. اگر احساس نمی‌کنید به همه ویژگی‌های موجود در Cloud Storage نیاز دارید یا نگران تأثیر آن بر هزینه هستید، می‌توانید در App Engine Blobstore بمانید.

فراتر از ماژول 16 تعداد زیادی انتقال احتمالی دیگر مانند Cloud NDB و Cloud Datastore، Cloud Tasks یا Cloud Memorystore وجود دارد. همچنین انتقال محصول متقابل به Cloud Run و Cloud Function وجود دارد. مخزن مهاجرت همه نمونه‌های کد را نشان می‌دهد، شما را به همه کدها و ویدیوهای موجود پیوند می‌دهد، و همچنین راهنمایی‌هایی را در مورد مهاجرت‌ها و هر «ترتیب» مربوط به مهاجرت ارائه می‌دهد.

7. منابع اضافی

مسائل/بازخوردهای Codelab

اگر مشکلی در این کد لبه پیدا کردید، لطفاً قبل از تشکیل پرونده ابتدا مشکل خود را جستجو کنید. پیوندهایی برای جستجو و ایجاد مسائل جدید:

منابع مهاجرت

پیوندهای پوشه‌های مخزن برای ماژول 0 (START) و ماژول 15 (FINISH) را می‌توانید در جدول زیر پیدا کنید. همچنین می‌توانید از مخزن برای همه انتقال‌های نرم‌افزار App Engine که می‌توانید یک فایل ZIP را شبیه‌سازی یا دانلود کنید، دسترسی پیدا کنید.

Codelab

پایتون 2

پایتون 3

ماژول 0

کد

N/A

ماژول 15 (این آزمایشگاه کد)

کد

N/A

منابع آنلاین

در زیر منابع آنلاینی وجود دارد که ممکن است برای این آموزش مرتبط باشد:

موتور برنامه

Google Cloud

پایتون

ویدیوها

مجوز

این اثر تحت مجوز Creative Commons Attribution 2.0 Generic مجوز دارد.