App Engine BLOBstore का इस्तेमाल कैसे करें (मॉड्यूल 15)

1. खास जानकारी

सर्वरलेस माइग्रेशन स्टेशन की कोडलैब सीरीज़ (अपने हिसाब से सीखने और प्रैक्टिकल करने वाले ट्यूटोरियल) और इससे जुड़े वीडियो का मकसद, Google Cloud सर्वरलेस डेवलपर की मदद करना है. इससे वे एक या उससे ज़्यादा माइग्रेशन करके, अपने ऐप्लिकेशन को बेहतर बना सकते हैं. इनमें मुख्य रूप से लेगसी सेवाओं से माइग्रेट करना शामिल है. ऐसा करने से, आपके ऐप्लिकेशन को एक जगह से दूसरी जगह ले जाना आसान हो जाता है. साथ ही, आपको ज़्यादा विकल्प और सुविधा मिलती है. इससे आपको Cloud प्रॉडक्ट की ज़्यादा रेंज के साथ इंटिग्रेट करने और उन्हें ऐक्सेस करने में मदद मिलती है. साथ ही, भाषा के नए वर्शन पर आसानी से अपग्रेड किया जा सकता है. शुरुआत में, इस सीरीज़ में मुख्य तौर पर App Engine (स्टैंडर्ड एनवायरमेंट) डेवलपर के लिए कॉन्टेंट शामिल किया गया था. हालांकि, अब इसमें अन्य सर्वरलेस प्लैटफ़ॉर्म के लिए भी कॉन्टेंट शामिल किया गया है. जैसे, Cloud Functions और Cloud Run. इसके अलावा, इसमें अन्य प्लैटफ़ॉर्म के लिए भी कॉन्टेंट शामिल किया गया है.

इस 15वें मॉड्यूल के कोडलैब में, यह बताया गया है कि मॉड्यूल 0 के सैंपल ऐप्लिकेशन में App Engine blobstore का इस्तेमाल कैसे किया जाता है. इसके बाद, मॉड्यूल 16 में Cloud Storage पर माइग्रेट करने के लिए तैयार हो जाएं.

आपको इनके बारे में जानकारी मिलेगी

  • App Engine Blobstore API/लाइब्रेरी के इस्तेमाल के बारे में जानकारी जोड़ें
  • यह कुकी, उपयोगकर्ता की अपलोड की गई फ़ाइलों को blobstore सेवा में सेव करती है
  • Cloud Storage पर माइग्रेट करने के लिए, अगले चरण की तैयारी करना

आपको किन चीज़ों की ज़रूरत होगी

सर्वे

इस ट्यूटोरियल का इस्तेमाल कैसे किया जाएगा?

सिर्फ़ इसे पढ़ें इसे पढ़ें और एक्सरसाइज़ पूरी करें

Python के साथ अपने अनुभव को आप क्या रेटिंग देंगे?

शुरुआती सामान्य एडवांस

Google Cloud की सेवाओं को इस्तेमाल करने के अपने अनुभव को आप क्या रेटिंग देंगे?

शुरुआती सामान्य एडवांस

2. बैकग्राउंड

App Engine Blobstore API से माइग्रेट करने के लिए, Module 0 से मौजूदा बेसलाइन App Engine ndb ऐप्लिकेशन में इसका इस्तेमाल जोड़ें. सैंपल ऐप्लिकेशन में, उपयोगकर्ता की हाल ही की दस विज़िट दिखाई जाती हैं. हम ऐप्लिकेशन में बदलाव कर रहे हैं, ताकि असली उपयोगकर्ता को एक आर्टफ़ैक्ट (फ़ाइल) अपलोड करने के लिए कहा जा सके. यह आर्टफ़ैक्ट, उसकी "विज़िट" से जुड़ा होना चाहिए. अगर उपयोगकर्ता ऐसा नहीं करना चाहता है, तो "अभी नहीं" विकल्प चुनें. उपयोगकर्ता के फ़ैसले से कोई फ़र्क़ नहीं पड़ता. अगला पेज, मॉड्यूल 0 (और इस सीरीज़ के कई अन्य मॉड्यूल) के ऐप्लिकेशन की तरह ही आउटपुट दिखाता है. App Engine blobstore इंटिग्रेशन लागू करने के बाद, हम इसे अगले (मॉड्यूल 16) कोडलैब में Cloud Storage पर माइग्रेट कर सकते हैं.

App Engine, Django और Jinja2 टेंप्लेटिंग सिस्टम का ऐक्सेस देता है. इस उदाहरण को अलग बनाने वाली एक चीज़ यह है कि इसमें Blobstore का ऐक्सेस जोड़ा गया है. इसके अलावा, इसमें Module 0 में Django का इस्तेमाल करने के बजाय, Module 15 में Jinja2 का इस्तेमाल किया गया है. App Engine ऐप्लिकेशन को आधुनिक बनाने का एक अहम तरीका यह है कि वेब फ़्रेमवर्क को webapp2 से Flask पर माइग्रेट किया जाए. बाद वाला सिस्टम, Jinja2 को डिफ़ॉल्ट टेंप्लेटिंग सिस्टम के तौर पर इस्तेमाल करता है. इसलिए, हम webapp2 पर रहते हुए Jinja2 को लागू करके, उस दिशा में आगे बढ़ना शुरू करते हैं. Flask, डिफ़ॉल्ट रूप से Jinja2 का इस्तेमाल करता है. इसका मतलब है कि मॉड्यूल 16 में, टेंप्लेट में कोई बदलाव करने की ज़रूरत नहीं होगी.

3. सेटअप/प्रीवर्क

ट्यूटोरियल के मुख्य हिस्से पर जाने से पहले, अपना प्रोजेक्ट सेट अप करें, कोड पाएं, और बेसलाइन ऐप्लिकेशन को डिप्लॉय करें, ताकि काम करने वाले कोड से शुरुआत की जा सके.

1. प्रोजेक्ट सेट अप करना

अगर आपने Module 0 ऐप्लिकेशन पहले ही डिप्लॉय कर दिया है, तो हमारा सुझाव है कि उसी प्रोजेक्ट और कोड का दोबारा इस्तेमाल करें. इसके अलावा, एक नया प्रोजेक्ट बनाया जा सकता है या किसी मौजूदा प्रोजेक्ट का फिर से इस्तेमाल किया जा सकता है. पक्का करें कि प्रोजेक्ट में, बिलिंग के लिए ऐक्टिव खाता हो और App Engine चालू हो.

2. बेसलाइन सैंपल ऐप्लिकेशन पाना

इस कोडलैब के लिए, यह ज़रूरी है कि आपके पास मॉड्यूल 0 का सैंपल ऐप्लिकेशन हो. अगर आपके पास यह नहीं है, तो इसे मॉड्यूल 0 के "START" फ़ोल्डर से डाउनलोड किया जा सकता है. इसका लिंक यहां दिया गया है. इस कोडलैब में, आपको हर चरण के बारे में बताया गया है. साथ ही, इसमें ऐसा कोड भी दिया गया है जो मॉड्यूल 15 के "FINISH" फ़ोल्डर में मौजूद कोड से मिलता-जुलता है.

मॉड्यूल 0 की STARTing फ़ाइलों की डायरेक्ट्री ऐसी दिखनी चाहिए:

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

3. बेसलाइन ऐप्लिकेशन को (फिर से) डिप्लॉय करना

अब आपको ये काम करने हैं:

  1. gcloud कमांड-लाइन टूल के बारे में फिर से जानें
  2. gcloud app deploy की मदद से, सैंपल ऐप्लिकेशन को फिर से डिप्लॉय करना
  3. पुष्टि करें कि ऐप्लिकेशन, App Engine पर बिना किसी समस्या के काम करता है

इन चरणों को पूरा करने के बाद, अगर आपको लगता है कि आपका वेब ऐप्लिकेशन काम कर रहा है (नीचे दिए गए उदाहरण की तरह), तो इसका मतलब है कि अब आप अपने ऐप्लिकेशन में कैश मेमोरी का इस्तेमाल कर सकते हैं.

a7a9d2b80d706a2b.png

4. कॉन्फ़िगरेशन फ़ाइलें अपडेट करना

app.yaml

ऐप्लिकेशन के कॉन्फ़िगरेशन में कोई अहम बदलाव नहीं किया गया है. हालांकि, जैसा कि पहले बताया गया है, हम Django टेंप्लेटिंग (डिफ़ॉल्ट) से Jinja2 पर माइग्रेट कर रहे हैं. इसलिए, स्विच करने के लिए उपयोगकर्ताओं को App Engine सर्वर पर उपलब्ध Jinja2 का नया वर्शन बताना होगा. इसके लिए, आपको इसे app.yaml के तीसरे पक्ष की बिल्ट-इन लाइब्रेरी सेक्शन में जोड़ना होगा.

BEFORE:

runtime: python27
threadsafe: yes
api_version: 1

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

अपनी app.yaml फ़ाइल में बदलाव करें. इसके लिए, यहां दिखाए गए तरीके से नया libraries सेक्शन जोड़ें:

AFTER:

runtime: python27
threadsafe: yes
api_version: 1

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

libraries:
- name: jinja2
  version: latest

किसी अन्य कॉन्फ़िगरेशन फ़ाइल को अपडेट करने की ज़रूरत नहीं है. इसलिए, ऐप्लिकेशन फ़ाइलों पर आगे बढ़ते हैं.

5. ऐप्लिकेशन की फ़ाइलों में बदलाव करना

इंपोर्ट और Jinja2 के साथ काम करने की सुविधा

main.py के लिए किए गए बदलावों के पहले सेट में, Blobstore API का इस्तेमाल करने की सुविधा जोड़ना और Django टेंप्लेटिंग को Jinja2 से बदलना शामिल है. यहां बताया गया है कि क्या-क्या बदलाव किए जा रहे हैं:

  1. os मॉड्यूल का मकसद, Django टेंप्लेट के लिए फ़ाइल का पाथनेम बनाना है. हम Jinja2 पर स्विच कर रहे हैं, जहां इस समस्या को ठीक किया जा सकता है. इसलिए, os के साथ-साथ Django टेंप्लेट रेंडरर, google.appengine.ext.webapp.template का इस्तेमाल करने की अब ज़रूरत नहीं है. इसलिए, इन्हें हटाया जा रहा है.
  2. Blobstore API इंपोर्ट करें: google.appengine.ext.blobstore
  3. ओरिजनल webapp फ़्रेमवर्क में मौजूद Blobstore हैंडलर इंपोर्ट करें. ये webapp2 में उपलब्ध नहीं हैं: google.appengine.ext.webapp.blobstore_handlers
  4. webapp2_extras पैकेज से Jinja2 के साथ काम करने की सुविधा इंपोर्ट करें

BEFORE:

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

ऊपर दी गई सूची में किए गए बदलावों को लागू करने के लिए, main.py में मौजूद मौजूदा इंपोर्ट सेक्शन को नीचे दिए गए कोड स्निपेट से बदलें.

AFTER:

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

इंपोर्ट करने के बाद, कुछ बॉयलरप्लेट कोड जोड़ें, ताकि webapp2_extras दस्तावेज़ में बताए गए तरीके से Jinja2 का इस्तेमाल किया जा सके. यहां दिया गया कोड स्निपेट, 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 के साथ काम करने की सुविधा जोड़ना

इस सीरीज़ के अन्य माइग्रेशन के उदाहरणों में, हम सैंपल ऐप्लिकेशन की सुविधाओं या आउटपुट को एक जैसा (या लगभग एक जैसा) रखते हैं. साथ ही, यूज़र एक्सपीरियंस में ज़्यादा बदलाव नहीं करते. हालांकि, इस उदाहरण में ऐसा नहीं किया गया है. हम ऐप्लिकेशन को अपडेट कर रहे हैं. इससे, उपयोगकर्ता से फ़ाइल आर्टफ़ैक्ट के लिए कहा जाएगा, ताकि उसकी विज़िट रजिस्टर की जा सके. ऐसा इसलिए किया जा रहा है, ताकि नई विज़िट को तुरंत रजिस्टर करने और हाल की दस विज़िट दिखाने के बजाय, उपयोगकर्ता की विज़िट को रजिस्टर किया जा सके. इसके बाद, असली उपयोगकर्ता के पास यह विकल्प होता है कि वह इससे जुड़ी कोई फ़ाइल अपलोड करे या "अभी नहीं" को चुनकर कोई भी फ़ाइल अपलोड न करे. यह चरण पूरा होने के बाद, "हाल ही की विज़िट" पेज दिखता है.

इस बदलाव से हमारा ऐप्लिकेशन, Blobstore सेवा का इस्तेमाल करके उस इमेज या अन्य फ़ाइल टाइप को हाल ही में विज़िट किए गए पेज पर सेव कर सकता है. साथ ही, बाद में उसे रेंडर भी कर सकता है.

डेटा मॉडल को अपडेट करना और उसका इस्तेमाल करना

हम ज़्यादा डेटा सेव कर रहे हैं. खास तौर पर, हम डेटा मॉडल को अपडेट कर रहे हैं, ताकि Blobstore में अपलोड की गई फ़ाइल के आईडी (इसे "BlobKey" कहा जाता है) को सेव किया जा सके. साथ ही, हम store_visit() में सेव करने के लिए एक रेफ़रंस जोड़ रहे हैं. क्वेरी करने पर, यह अतिरिक्त डेटा अन्य सभी डेटा के साथ वापस मिलता है. इसलिए, fetch_visits() में कोई बदलाव नहीं होता.

इन अपडेट के बाद, file_blob की ndb.BlobKeyProperty में क्या बदलाव हुए, यहां देखें:

BEFORE:

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)

AFTER:

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, google.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandler से मिले नए UploadHandler को कंट्रोल करने का ऐक्सेस देता है.
  3. UploadHandler की POST विधि, अपलोड करती है. यह विज़िट रजिस्टर करने के लिए store_visit() को कॉल करती है. साथ ही, उपयोगकर्ता को "/" पर वापस भेजने के लिए, एचटीटीपी 307 रीडायरेक्ट को ट्रिगर करती है. यहां...
  4. मुख्य हैंडलर का POST तरीका, fetch_visits() के ज़रिए क्वेरी करता है और हाल ही की विज़िट दिखाता है. अगर उपयोगकर्ता "अभी नहीं" विकल्प चुनता है, तो कोई फ़ाइल अपलोड नहीं होती. हालांकि, विज़िट अब भी रजिस्टर होती है और उपयोगकर्ता को उसी पेज पर रीडायरेक्ट किया जाता है.
  5. हाल ही की विज़िट की जानकारी में, उपयोगकर्ता को एक नया फ़ील्ड दिखता है. अगर अपलोड की गई फ़ाइल उपलब्ध है, तो हाइपरलिंक किया गया "देखें" विकल्प दिखता है. अगर फ़ाइल उपलब्ध नहीं है, तो "कोई नहीं" विकल्प दिखता है. ये बदलाव एचटीएमएल टेंप्लेट में किए गए हैं. साथ ही, इसमें अपलोड फ़ॉर्म भी जोड़ा गया है. इसके बारे में जल्द ही ज़्यादा जानकारी दी जाएगी.
  6. अगर कोई व्यक्ति, अपलोड किए गए वीडियो के साथ किसी विज़िट के लिए "देखें" लिंक पर क्लिक करता है, तो यह GET से मिले नए ViewBlobHandler को GET अनुरोध करता है. इससे, अगर कोई इमेज (अगर ब्राउज़र में काम करती है, तो ब्राउज़र में) है, तो फ़ाइल रेंडर हो जाती है. अगर ऐसा नहीं होता है, तो फ़ाइल डाउनलोड करने का अनुरोध किया जाता है. अगर फ़ाइल नहीं मिलती है, तो HTTP 404 गड़बड़ी का मैसेज दिखता है.google.appengine.ext.webapp.blobstore_handlers.BlobstoreDownloadHandler
  7. हैंडलर क्लास के नए पेयर और ट्रैफ़िक भेजने के लिए रास्तों के नए पेयर के अलावा, मुख्य हैंडलर को ऊपर बताए गए 307 रीडायरेक्ट को पाने के लिए, एक नए POST तरीके की ज़रूरत होती है.

इन अपडेट से पहले, Module 0 ऐप्लिकेशन में सिर्फ़ एक मुख्य हैंडलर था. इसमें GET तरीका और एक ही रूट था:

BEFORE:

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) GET तरीके वाला "व्यू ब्लब" डाउनलोड हैंडलर, और 3) GET और POST तरीकों वाला मुख्य हैंडलर. ये बदलाव करें, ताकि आपका बाकी ऐप्लिकेशन अब नीचे दिए गए ऐप्लिकेशन की तरह दिखे.

AFTER:

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 को कॉल किया गया है. यह कॉल, फ़ॉर्म के यूआरएल को जनरेट करता है. साथ ही, अपलोड हैंडलर को कॉल करके फ़ाइल को Blobstore पर भेजता है.POST
  • UploadHandler.post में, blobstore_handlers.BlobstoreUploadHandler.get_uploads को कॉल किया गया है. यह असली मैजिक है, जो फ़ाइल को Blobstore में डालता है. साथ ही, उस फ़ाइल के लिए यूनीक और स्थायी आईडी, यानी कि BlobKey दिखाता है.
  • ViewBlobHandler.get में, फ़ाइल के BlobKey के साथ blobstore_handlers.BlobstoreDownloadHandler.send को कॉल करने पर, फ़ाइल फ़ेच हो जाती है और इसे उपयोगकर्ता के ब्राउज़र पर भेज दिया जाता है

इन कॉल से, ऐप्लिकेशन में जोड़ी गई सुविधाओं को ऐक्सेस किया जाता है. main.py में किए गए दूसरे और आखिरी बदलावों के बारे में यहां इमेज में बताया गया है:

da2960525ac1b90d.png

एचटीएमएल टेंप्लेट अपडेट करना

मुख्य ऐप्लिकेशन में किए गए कुछ अपडेट, ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) पर असर डालते हैं. इसलिए, वेब टेंप्लेट में भी बदलाव करने पड़ते हैं. दरअसल, दो बदलाव करने पड़ते हैं:

  1. फ़ाइल अपलोड करने के लिए, तीन इनपुट एलिमेंट वाला फ़ॉर्म ज़रूरी है: एक फ़ाइल और फ़ाइल अपलोड करने और स्किप करने के लिए, सबमिट बटन का एक पेयर.
  2. हाल ही की विज़िट के आउटपुट को अपडेट करें. इसके लिए, विज़िट के लिए "देखें" लिंक जोड़ें. अगर विज़िट से जुड़ी कोई फ़ाइल अपलोड की गई है, तो "कोई नहीं" चुनें.

BEFORE:

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

अपडेट किए गए टेंप्लेट को शामिल करने के लिए, ऊपर दी गई सूची में मौजूद बदलाव लागू करें:

AFTER:

<!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 को उसमें ले जाएं. इस आखिरी बदलाव के बाद, आपने Module 0 के सैंपल ऐप्लिकेशन में Blobstore का इस्तेमाल करने के लिए ज़रूरी सभी बदलाव कर लिए हैं.

(वैकल्पिक) Cloud Storage "बेहतर"

Blobstore स्टोरेज को बाद में Cloud Storage में बदल दिया गया. इसका मतलब है कि Blobstore में अपलोड किए गए डेटा को Cloud Console में देखा जा सकता है. खास तौर पर, Cloud Storage ब्राउज़र में. सवाल यह है कि कहां. जवाब, आपके App Engine ऐप्लिकेशन का डिफ़ॉल्ट Cloud Storage बकेट है. इसका नाम, आपके 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')

इमेज के टाइप की पुष्टि करने के लिए, Python Standard Library imghdr मॉड्यूल जैसे टूल का इस्तेमाल करके, अपलोड की गई इमेज की पुष्टि करें. आखिर में, आपको नुकसान पहुंचाने वाले लोगों या इकाइयों के लिए, अपलोड किए जाने वाले डेटा का साइज़ सीमित करना पड़ सकता है.

मान लें कि यह सब हो चुका है. हम अपने ऐप्लिकेशन को कैसे अपडेट करें, ताकि यह बताया जा सके कि अपलोड की गई फ़ाइलों को कहां सेव करना है? MainHandler.get में blobstore.create_upload_url को बदलकर, Cloud Storage में अपलोड करने के लिए अपनी पसंद की जगह तय की जा सकती है. इसके लिए, gs_bucket_name पैरामीटर को इस तरह जोड़ें:

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

यह एक वैकल्पिक अपडेट है. अगर आपको यह बताना है कि अपलोड किए गए आइटम कहां जाने चाहिए, तो यह अपडेट ज़रूरी है. इसलिए, यह अपडेट repo में मौजूद main.py फ़ाइल का हिस्सा नहीं है. इसके बजाय, main-gcs.py नाम का एक विकल्प, repo में आपकी समीक्षा के लिए उपलब्ध है. main.py की तरह, main-gcs.py में मौजूद कोड, अपलोड किए गए डेटा को "रूट" बकेट (PROJECT_ID.appspot.com) में सेव करता है. इसके लिए, अलग बकेट "फ़ोल्डर" का इस्तेमाल नहीं किया जाता. हालांकि, अगर आपको इस सेक्शन में बताए गए तरीके से सैंपल को किसी और चीज़ में बदलना है, तो main-gcs.py आपको ज़रूरी ढांचा उपलब्ध कराता है. यहां main.py और main-gcs.py के बीच के "अंतर" को दिखाया गया है.

256e1ea68241a501.png

6. खास जानकारी/सफ़ाई

इस सेक्शन में, ऐप्लिकेशन को डिप्लॉय करके इस कोडलैब को पूरा किया गया है. साथ ही, यह पुष्टि की गई है कि ऐप्लिकेशन ठीक से काम कर रहा है और आउटपुट में कोई गड़बड़ी नहीं है. ऐप्लिकेशन की पुष्टि होने के बाद, क्लीन-अप से जुड़े सभी चरण पूरे करें और आगे की कार्रवाई करें.

ऐप्लिकेशन डिप्लॉय करना और उसकी पुष्टि करना

gcloud app deploy की मदद से, अपने ऐप्लिकेशन को फिर से डिप्लॉय करें. साथ ही, पुष्टि करें कि ऐप्लिकेशन, विज्ञापन में बताए गए तरीके से काम करता है. यह भी पुष्टि करें कि ऐप्लिकेशन का उपयोगकर्ता अनुभव (यूएक्स), मॉड्यूल 0 वाले ऐप्लिकेशन से अलग है. अब आपके ऐप्लिकेशन में दो अलग-अलग स्क्रीन हैं. पहली स्क्रीन, विज़िट फ़ाइल अपलोड करने के फ़ॉर्म का प्रॉम्प्ट है:

f5b5f9f19d8ae978.pngयहाँ से, असली उपयोगकर्ता या तो कोई फ़ाइल अपलोड करके "सबमिट करें" पर क्लिक करते हैं या कुछ भी अपलोड न करने के लिए "स्किप करें" पर क्लिक करते हैं. दोनों ही मामलों में, नतीजे के तौर पर विज़िट की सबसे नई स्क्रीन दिखती है. अब इसमें विज़िट के टाइमस्टैंप और विज़िटर की जानकारी के बीच "देखें" लिंक या "कोई नहीं" जोड़ा गया है:

f5ac6b98ee8a34cb.png

Module 0 के सैंपल ऐप्लिकेशन में App Engine Blobstore का इस्तेमाल करने के लिए, इस कोडलैब को पूरा करने पर बधाई. अब आपका कोड, FINISH (Module 15) फ़ोल्डर में मौजूद कोड से मेल खाना चाहिए. उस फ़ोल्डर में, विकल्प main-gcs.py भी मौजूद है.

व्यवस्थित करें

सामान्य

अगर आपको अभी और काम नहीं करना है, तो हमारा सुझाव है कि आप अपने App Engine ऐप्लिकेशन को बंद कर दें, ताकि आपसे शुल्क न लिया जाए. हालांकि, अगर आपको कुछ और टेस्ट या एक्सपेरिमेंट करने हैं, तो App Engine प्लैटफ़ॉर्म पर मुफ़्त कोटा उपलब्ध है. इसलिए, जब तक आप इस्तेमाल की उस सीमा से ज़्यादा नहीं होते हैं, तब तक आपसे कोई शुल्क नहीं लिया जाएगा. यह शुल्क कंप्यूट के लिए है. हालांकि, App Engine की सेवाओं के लिए भी शुल्क लिया जा सकता है. इसलिए, ज़्यादा जानकारी के लिए कीमत वाला पेज देखें. अगर इस माइग्रेशन में अन्य क्लाउड सेवाएं शामिल हैं, तो उनके लिए अलग से बिल भेजा जाता है. अगर लागू हो, तो दोनों ही मामलों में, नीचे दिया गया "इस कोडलैब के लिए खास जानकारी" सेक्शन देखें.

पूरी जानकारी के लिए बता दें कि App Engine जैसे Google Cloud के सर्वरलेस कंप्यूट प्लैटफ़ॉर्म पर डिप्लॉय करने से, बिल्ड और स्टोरेज के लिए मामूली शुल्क लगता है. 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*ation पर निर्भर करते हैं. उदाहरण के लिए, अगर आपका ऐप्लिकेशन अमेरिका में होस्ट किया गया है, तो "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 Functions पर, अलग-अलग प्रॉडक्ट के माइग्रेशन भी किए जा सकते हैं. माइग्रेशन रेपो में सभी कोड सैंपल मौजूद हैं. साथ ही, इसमें उपलब्ध सभी कोडलैब और वीडियो के लिंक भी दिए गए हैं. इसमें यह भी बताया गया है कि किन माइग्रेशन पर विचार करना चाहिए और माइग्रेशन का कोई भी ज़रूरी "क्रम" क्या है.

7. अन्य संसाधन

कोडलैब से जुड़ी समस्याएं/सुझाव/राय

अगर आपको इस कोडलैब में कोई समस्या मिलती है, तो कृपया शिकायत दर्ज करने से पहले अपनी समस्या खोजें. नई समस्याएं खोजने और बनाने के लिए लिंक:

माइग्रेशन के लिए उपलब्ध संसाधन

मॉड्यूल 0 (START) और मॉड्यूल 15 (FINISH) के लिए, रेपो फ़ोल्डर के लिंक नीचे दी गई टेबल में देखे जा सकते हैं. इन्हें App Engine के सभी कोडलैब माइग्रेशन के लिए उपलब्ध repo से भी ऐक्सेस किया जा सकता है. इसे क्लोन किया जा सकता है या इसकी ZIP फ़ाइल डाउनलोड की जा सकती है.

कोडलैब

Python 2

Python 3

मॉड्यूल 0

code

लागू नहीं

मॉड्यूल 15 (यह कोडलैब)

code

लागू नहीं

ऑनलाइन संसाधन

यहां कुछ ऑनलाइन संसाधन दिए गए हैं, जो इस ट्यूटोरियल के लिए काम के हो सकते हैं:

App Engine

Google Cloud

Python

वीडियो

लाइसेंस

इस काम के लिए, Creative Commons एट्रिब्यूशन 2.0 जेनेरिक लाइसेंस के तहत लाइसेंस मिला है.