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

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

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

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

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

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

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

सर्वे

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

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

Python इस्तेमाल करने का आपका अनुभव कैसा रहा?

शुरुआती इंटरमीडिएट कुशल

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

शुरुआती इंटरमीडिएट कुशल

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

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

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

3. सेटअप/पहले से की जाने वाली तैयारी

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

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

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

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

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

मॉड्यूल 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

ऐप्लिकेशन के कॉन्फ़िगरेशन में कोई खास बदलाव नहीं किया गया है. हालांकि, जैसा कि पहले बताया गया है, हम Django टेंप्लेट (डिफ़ॉल्ट) से Jinja2 पर स्विच कर रहे हैं. इसलिए, स्विच करने के लिए उपयोगकर्ताओं को App Engine सर्वर पर उपलब्ध Jinja2 का नया वर्शन बताना होगा. इसके लिए, आपको इसे 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 का इस्तेमाल करना और 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 सहायता इंपोर्ट करें

पहले:

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

पहले:

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

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

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

da2960525ac1b90d.png

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

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

  1. फ़ाइल अपलोड करने के लिए एक फ़ॉर्म की ज़रूरत होती है. इसमें तीन इनपुट एलिमेंट होने चाहिए: एक फ़ाइल और सबमिट करने के लिए दो बटन. इनमें से एक बटन फ़ाइल अपलोड करने के लिए और दूसरा बटन फ़ाइल अपलोड करने की प्रोसेस को स्किप करने के लिए होता है.
  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 को उसमें ले जाएं. इस आखिरी चरण के साथ, आपने मॉड्यूल 0 के सैंपल के तौर पर मिले ऐप्लिकेशन में Blobstore का इस्तेमाल करने के लिए ज़रूरी सभी बदलाव कर लिए हैं.

(ज़रूरी नहीं) Cloud Storage "enhancement"

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

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

256e1ea68241a501.png

6. खास जानकारी/क्लीनअप

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

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

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

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

f5ac6b98ee8a34cb.png

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

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

सामान्य

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

पूरी जानकारी के लिए, 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*पर निर्भर करते हैं. उदाहरण के लिए, अगर आपका ऐप्लिकेशन अमेरिका में होस्ट किया गया है, तो "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 कोडलैब माइग्रेशन के लिए रेपो से भी ऐक्सेस किया जा सकता है. इसे क्लोन किया जा सकता है या ZIP फ़ाइल के तौर पर डाउनलोड किया जा सकता है.

Codelab

Python 2

Python 3

मॉड्यूल 0

कोड

लागू नहीं

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

कोड

लागू नहीं

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

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

App Engine

Google Cloud

Python

वीडियो

लाइसेंस

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