読み込んでいます...
一致する結果は見つかりませんでした。

Google Cloud コンソールでスキルを試す

03

Developing Applications with Google Cloud: Foundations

700 以上のラボとコースにアクセス

Google Cloud でアプリケーションを開発する: アプリケーションにユーザー認証とインテリジェンスを追加する

ラボ 1時間 30分 universal_currency_alt クレジット: 5 show_chart 中級
info このラボでは、学習をサポートする AI ツールが組み込まれている場合があります。
700 以上のラボとコースにアクセス

概要

Cloud クライアント ライブラリは、アプリケーションから Google Cloud API を呼び出すための推奨される方法です。Cloud クライアント ライブラリでは、アプリケーションで使用しているプログラミング言語の自然な規則やスタイルを使用します。Cloud クライアント ライブラリは、認証や再試行ロジックなど、サーバーとの下位レベルの通信を処理します。

Firestore は、高速、フルマネージド、かつサーバーレスの NoSQL ドキュメント データベースで、自動スケーリング、高パフォーマンス、アプリケーション開発のしやすさを念頭に置いて設計されています。

Google API では、認証および承認に OAuth 2.0 プロトコルを使用しています。

Secret Manager では、API キー、パスワード、証明書、その他の機密データをバイナリ blob またはテキスト文字列として保存できます。

Cloud Translation API を使用すると、ウェブサイトやアプリケーションで、プログラムによってテキストを動的に翻訳できます。Cloud Translation では 100 を超える言語のテキストを翻訳でき、ソーステキストの言語を検出できます。

このラボでは、書籍のリストを管理する Python アプリケーションを更新します。OAuth を使用してアプリケーションにログインする機能を追加し、書籍の追加、編集、削除時にユーザーにログインを求めます。

また、Cloud Translation API を使用して、書籍の説明を別の言語に翻訳します。ユーザーの設定言語を保存するユーザー プロファイルを追加します。

学習内容

このラボでは、次のタスクの実行方法を学びます。

  • 簡単な Python Flask ウェブ アプリケーションを作成する。
  • Secret Manager を使用して、機密性の高いアプリケーション データを保存する。
  • OAuth 2.0 を使用して、アプリケーションにユーザー ログインを追加する。
  • Cloud Translation API を使用して、テキストの言語を検出し、テキストを翻訳する。

設定と要件

[ラボを開始] ボタンをクリックする前に

注: 以下の説明をお読みください。

ラボの時間は計測されており、一時停止することはできません。[ラボを開始] をクリックするとスタートするタイマーは、Google Cloud のリソースを利用できる時間を示しています。

この Qwiklabs ハンズオンラボでは、シミュレーションやデモ環境ではなく、実際のクラウド環境を使ってご自身でラボのアクティビティを行うことができます。そのため、ラボの受講中に Google Cloud にログインおよびアクセスするための、新しい一時的な認証情報が提供されます。

必要なもの

このラボを完了するためには、下記が必要です。

  • 標準的なインターネット ブラウザ(Chrome を推奨)
  • ラボを完了するために十分な時間
注: すでに個人の Google Cloud アカウントやプロジェクトをお持ちの場合でも、ラボでは使用しないでください。 注: Pixelbook を使用している場合は、このラボをシークレット ウィンドウで実施してください。

ラボを開始してコンソールにログインする方法

  1. [ラボを開始] ボタンをクリックします。ラボの料金をお支払いいただく必要がある場合は、表示されるポップアップでお支払い方法を選択してください。 左側のパネルには、このラボで使用する必要がある一時的な認証情報が表示されます。

  2. ユーザー名をコピーし、[Google Console を開く] をクリックします。 ラボでリソースが起動し、別のタブで [アカウントの選択] ページが表示されます。

    注: タブをそれぞれ別のウィンドウで開き、並べて表示しておきましょう。
  3. [アカウントの選択] ページで [別のアカウントを使用] をクリックします。[ログイン] ページが開きます。

  4. [接続の詳細] パネルでコピーしたユーザー名を貼り付けます。パスワードもコピーして貼り付けます。

注: 認証情報は [接続の詳細] パネルに表示されたものを使用してください。Google Cloud Skills Boost の認証情報は使用しないでください。請求が発生する事態を避けるため、Google Cloud アカウントをお持ちの場合でも、このラボでは使用しないでください。
  1. その後次のように進みます。
  • 利用規約に同意してください。
  • 一時的なアカウントなので、復元オプションや 2 要素認証プロセスは設定しないでください。
  • 無料トライアルには登録しないでください。

しばらくすると、このタブで Cloud コンソールが開きます。

注: 左上にある [ナビゲーション メニュー] をクリックすると、Google Cloud のプロダクトやサービスのリストが含まれるメニューが表示されます。

Google Cloud Shell の有効化

Google Cloud Shell は、開発ツールと一緒に読み込まれる仮想マシンです。5 GB の永続ホーム ディレクトリが用意されており、Google Cloud で稼働します。

Google Cloud Shell を使用すると、コマンドラインで Google Cloud リソースにアクセスできます。

  1. Google Cloud コンソールで、右上のツールバーにある [Cloud Shell をアクティブにする] ボタンをクリックします。

  2. [続行] をクリックします。

環境がプロビジョニングされ、接続されるまでしばらく待ちます。接続した時点で認証が完了しており、プロジェクトに各自のプロジェクト ID が設定されます。次に例を示します。

gcloud は Google Cloud のコマンドライン ツールです。このツールは、Cloud Shell にプリインストールされており、タブ補完がサポートされています。

  • 次のコマンドを使用すると、有効なアカウント名を一覧表示できます。
gcloud auth list

出力:

Credentialed accounts: - @.com (active)

出力例:

Credentialed accounts: - google1623327_student@qwiklabs.net
  • 次のコマンドを使用すると、プロジェクト ID を一覧表示できます。
gcloud config list project

出力:

[core] project =

出力例:

[core] project = qwiklabs-gcp-44776a13dea667a6 注: gcloud ドキュメントの全文については、 gcloud CLI の概要ガイド をご覧ください。

タスク 1. Python アプリケーションと必要なリソースを設定する

このタスクでは、Python アプリケーションをダウンロードして、現在のバージョンのアプリで使用されるリソースを作成します。

注: ほとんどの言語では、コードを読みやすくするためにインデントが使用されます。Python ではインデントを使用してコードのブロックを示すため、インデントが正確でなければなりません。インデントに使用するスペースの数は、一貫している必要があります。インデントにスペースとタブを混在させると、問題が発生する可能性があります。このラボでは、Python のインデントに 4 つのスペースを使用します。

Firestore データベースを作成する

  1. Firestore データベースを作成するには、Cloud Shell で次のコマンドを実行します。

    gcloud firestore databases create --location={{{ project_0.default_region | region }}}

    Firestore データベースは、書籍とユーザー プロファイル データを保存するために使用されます。

  2. Cloud Shell を承認するように求められたら、[承認] をクリックします。

適切な権限で Cloud Storage バケットを作成する

  1. Cloud Storage バケットを作成するには、次のコマンドを実行します。

    gcloud storage buckets create gs://{{{ project_0.project_id | project_id}}}-covers --location={{{ project_0.default_region | region }}} --no-public-access-prevention --uniform-bucket-level-access

    Cloud Storage バケットは、書籍の表紙画像を保存するために使用されます。このバケットには均一なバケットレベルのアクセスがあり、公開アクセスの防止を使用していません。

    注: コマンドが失敗し、アカウントに有効な認証情報がないことを示すエラーが表示された場合は、コマンドを再度実行してみてください。Qwiklabs の学生アカウントの権限がまだ反映されていない可能性があります。
  2. バケット内のすべてのオブジェクトを一般公開するには、次のコマンドを実行します。

    gcloud storage buckets add-iam-policy-binding gs://{{{ project_0.project_id | project_id}}}-covers --member=allUsers --role=roles/storage.legacyObjectReader

[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。 Python アプリケーションと必要なリソースを設定する

Python コードを Cloud Shell にコピーする

  1. Cloud Storage バケットからルート ディレクトリに Python コードをコピーするには、次のコマンドを実行します。

    gcloud storage cp -r gs://cloud-training/devapps-foundations/code/lab2/bookshelf ~
  2. bookshelf ディレクトリの内容を確認するには、次のコマンドを実行します。

    cd ~ ls -R bookshelf

    次のような 3 つの Python ファイル、1 つの要件ファイル、4 つのテンプレート ファイルを含むリストが表示されます。

    bookshelf: booksdb.py main.py requirements.txt storage.py templates bookshelf/templates: base.html form.html list.html view.html

必要な依存関係をインストールする

  1. 要件ファイル内の依存関係を表示するには、次のコマンドを実行します。

    cat ~/bookshelf/requirements.txt

    要件ファイルでは、次の依存関係を指定します。

    • Flask: Python ウェブ アプリケーションの設計に使用されるウェブ フレームワーク モジュール
    • Gunicorn: Linux で動作する Python HTTP サーバー
    • Cloud Logging: アプリケーションからの情報の記録に使用
    • Firestore: アプリケーション開発のしやすさを念頭に置いて設計された、高速、フルマネージド、かつサーバーレスの NoSQL ドキュメント データベース
    • Cloud Storage: Google Cloud の統合オブジェクト ストレージ
  2. 要件ファイル内の依存関係をインストールするには、次のコマンドを実行します。

    pip3 install -r ~/bookshelf/requirements.txt --user

    pip は Python 用のパッケージ インストーラです。この pip3 コマンドは、Python バージョン 3 で使用するために requirements.txt ファイルで指定されたパッケージをインストールします。

アプリケーションをテストする

  1. アプリケーションを開始するには、次のコマンドを実行します。

    cd ~/bookshelf; ~/.local/bin/gunicorn -b :8080 main:app

    ファイルを正常に作成した場合、アプリケーションはポート 8080 でホストされます。

  2. ウェブブラウザでアプリケーションを実行するには、[ウェブでプレビュー] をクリックし、[ポート 8080 でプレビュー] を選択します。

    ブラウザで新しいタブが開き、アプリケーションが実行されます。このページには、既存のすべての書籍のリストが表示されます。まだ書籍はありません。

    注: Cloud Shell を承認するよう求められたら、[承認] をクリックします。
  3. この「オズの魔法使い」の書籍の表紙画像を右クリックし、oz.png という名前でパソコンに保存します。

  4. [アプリケーション] タブで、[+ 書籍の追加] クリックします。

  5. フォームに次の情報を入力します。

    フィールド
    タイトル オズの魔法使い
    著者 Frank L. Baum
    出版日 1900
    説明 少女と飼い犬が魔法の国にたどり着き、そこで沢山の風変わりな登場人物に出会い、家の下にいてはいけないことを学ぶ。
  6. [表紙の画像] で、[ファイルを選択] をクリックします。

  7. ダウンロードしたファイル(oz.png)を選択し、[開く] をクリックします。

  8. [保存] をクリックします。

    表示ページに戻ると、書籍の詳細が表示されます。

  9. ページ上部の [書籍] をクリックします。

    リストページに戻り、「オズの魔法使い」がリストに書籍の表紙とともに表示されます。書籍の詳細は Firestore データベースに保存され、表紙の画像は Cloud Storage に保存されます。

    注: 他の書籍を追加することはできますが、「オズの魔法使い」は変更しません。「オズの魔法使い」はこのラボの以降の部分で使用します。
  10. Cloud Shell でアプリケーションを終了するには、Ctrl+C キーを押します。

[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。 アプリケーションをテストして書籍を作成する

タスク 2. アプリケーションの OAuth 認証情報を作成する

このタスクでは、Google の OAuth 2.0 サーバーにアプリケーションを識別させる認証情報を作成します。

OAuth 同意画面を作成する

認証に OAuth 2.0 を使用する場合、アプリでは Google アカウントから 1 つ以上のアクセス スコープがリクエストされます。Google が同意画面を表示して、アプリケーションとデータを共有することに対するユーザーの同意を得ます。

  1. Google Cloud コンソールで、ナビゲーション メニュー)を選択し、[API とサービス] > [OAuth 同意画面] を選択します。

    このページでは、アプリケーションを使用するユーザーのタイプを選択できます。内部ユーザーは組織内のユーザーです。外部ユーザーは Google アカウントを持つすべてのユーザーです。

  2. [利用開始] をクリックします。

  3. [アプリ名] に「Bookshelf」と入力します。

  4. [ユーザー サポートメール] で、受講者のメールアドレスを選択します。

  5. [次へ] をクリックします。

  6. [対象] で [外部] を選択し、[次へ] をクリックします。

    テスト アカウントを持つユーザーは、アプリにログインできるようになります。

  7. ラボの手順の左側にあるパネルで、[ユーザー名] の値をコピーします。

  8. [メールアドレス] では、コピーしたユーザー名を貼り付けて、[次へ] をクリックします。

  9. ユーザーデータに関するポリシーに同意するチェックボックスをオンにして、[続行] をクリックします。

  10. [作成] をクリックします。

  11. ナビゲーション メニューで、[ブランディング] をクリックします。

  12. [+ ドメインの追加] をクリックします。

  13. [承認済みドメイン] セクションで、[承認済みドメイン 1] に「cloudshell.dev」と入力します。

    アプリケーションが Cloud Shell で実行されている場合、ドメイン名は cloudshell.dev です。

  14. [保存] をクリックします。

  15. ナビゲーション メニューで [データアクセス] をクリックします。

    次に、アプリケーションでユーザーに要求するスコープを選択する必要があります。スコープは、アプリケーションがアクセスするユーザーの Google アカウント内のプライベートなユーザーデータの種類を表します。

    スコープには次の 3 つの種類があります。

    • プライベート データにかかわるスコープは、同意画面でユーザーに提示する前に、Google による確認を受ける必要があります。
    • 制限付きスコープには、Gmail やドライブなどのアプリから取得される、さらに機密性の高い情報が含まれます。そのため、より範囲の広い審査が必要になる場合があります。
    • センシティブでないスコープは、機密性が低く、Google による確認を必要としないスコープです。
  16. [スコープを追加または削除] をクリックします。

    スコープのリストが表示されます。

  17. リストの先頭で、openid の横にあるチェックボックスをオンにします。

  18. [フィルタ] に「userinfo.profile」と入力して Enter キーを押してから、[.../auth/userinfo.profile] スコープの横にあるチェックボックスをオンにします。

  19. [フィルタ] の「userinfo.profile」フィルタをクリアし、「contacts」と入力して Enter キーを押します。次に、[.../auth/contacts] スコープのチェックボックスをオンにします。

  20. [更新] をクリックします。

    センシティブでないスコープが 2 つ(openid と userinfo.profile)と、プライベート データにかかわるスコープが 1 つ(contacts)表示されます。

    注: このラボでは contacts スコープは使用しませんが、例として使用しています。アプリケーションには、アプリケーションに必要な最小限のスコープを使用する必要があります。
  21. [保存] をクリックします。

  22. ナビゲーション メニューで、[対象] をクリックします。

    ユーザーが外部ユーザーで、公開ステータスが [テスト中] に設定されている場合は、テストユーザーが必要です。

  23. [+ ユーザーを追加] をクリックします。

  24. ラボの手順の左側にあるパネルで、[ユーザー名] を再度コピーします。

  25. [ユーザーを追加] ペインで、コピーしたユーザー名をボックスに貼り付け、[保存] をクリックします。

OAuth 2.0 認証情報を作成する

  1. ナビゲーション メニューで [クライアント]、[+ クライアントを作成] の順にクリックします。

  2. [アプリケーションの種類] で [ウェブ アプリケーション] を選択します。

  3. [名前] に「Bookshelf」と入力します。

  4. [承認済みのリダイレクト URI] で [+ URI を追加] をクリックします。

    ここに指定した URI は、ユーザーの同意を取得した後に Google がブラウザをアプリケーションにリダイレクトする際に使用されます。

  5. リダイレクト URI を取得するには、Cloud Shell で次のコマンドを実行します。

    echo "https://8080-${WEB_HOST}/oauth2callback"
  6. echo コマンドで作成した URI をコピーし、[URIs 1] に貼り付けます。

  7. [作成] をクリックします。

  8. OAuth 2.0 クライアント ID [Bookshelf] の [操作] 列で、[OAuth クライアントをダウンロード]()をクリックします。

  9. [JSON をダウンロード] をクリックし、クライアント シークレット JSON をローカルマシンに保存します。

    クライアント シークレット ファイルは、Google でアプリを検証するために使用されます。

  10. [閉じる] をクリックします。

  11. Cloud Shell で、右上のツールバーの [さらに表示]()をクリックし、[アップロード] をクリックします。

  12. [ファイル選択] をクリックし、クライアント シークレット JSON ファイルを選択して、[開く] をクリックします。

  13. [アップロード] をクリックします。

    これで、クライアント シークレット JSON ファイルをホーム ディレクトリで使用できるようになりました。このファイルの内容は、OAuth プロセスで使用されます。

  14. Cloud Shell で、次のコマンドを実行します。

    cat ~/client_secret_*.json

    JSON の内容には、パスワードのように扱う必要がある client_secret が含まれています。たとえば、この JSON ファイルをコード リポジトリに保存することは決して望ましくありません。

クライアント シークレット JSON を Secret Manager に保存する

クライアント シークレット JSON ファイルの保存先として、安全な Secret Manager を使用することをおすすめします。

  1. Secret Manager API を有効にするには、次のコマンドを実行します。

    gcloud services enable secretmanager.googleapis.com
  2. クライアント シークレット ファイルの名前を変更するには、次のコマンドを実行します。

    mv ~/client_secret*.json ~/client_secret.json
  3. シークレットを作成するには、次のコマンドを実行します。

    gcloud secrets create bookshelf-client-secrets --data-file=$HOME/client_secret.json

    これで、アプリケーションからアクセスできる bookshelf-client-secrets という名前のシークレットが作成されました。

    アプリケーションに必要なもう 1 つのシークレット値は、Flask 秘密鍵です。これは、Cookie 内の情報に署名するために使用されます。

  4. Flask 秘密鍵のシークレットを作成するには、次のコマンドを実行します。

    tr -dc A-Za-z0-9 </dev/urandom | head -c 20 | gcloud secrets create flask-secret-key --data-file=-

    このコマンドにより、20 文字のランダムな英数字のパスワードが作成され、flask-secret-key という名前のシークレットに保存されます。

[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。 アプリケーションの OAuth 認証情報を作成する

タスク 3. アプリケーションでシークレットを取得するために Secret Manager を使用する

このタスクでは、Secret Manager を使用できるようにアプリケーションを変更します。

要件ファイルを変更して Secret Manager を追加する

  1. 次のコマンドを使用して、requirements.txt というファイルを nano で開きます。

    nano ~/bookshelf/requirements.txt
  2. requirements ファイル内で、下矢印を使用して最初の空白行に移動し、次の行を追加します。

    google-cloud-secret-manager==2.16.4

    requirements.txt ファイルは次のようになります。

    Flask==2.3.3 gunicorn==21.2.0 google-cloud-logging==3.6.0 google-cloud-firestore==2.12.0 google-cloud-storage==2.10.0 google-cloud-secret-manager==2.16.4
  3. ファイルを保存して終了するには、Ctrl+X、Y キー、Enter キーの順に押します。

  4. 依存関係の更新バージョンをインストールするには、次のコマンドを実行します。

    pip3 install -r ~/bookshelf/requirements.txt --user

シークレットを取得する関数を作成する

secrets.py ファイルには、Secret Manager からシークレットを取得するコードが含まれています。

  1. secrets.py ファイルを作成するには、次のコマンドを実行します。

    cat > ~/bookshelf/secrets.py <<EOF import os from google.cloud import secretmanager def get_secret(secret_id, version_id='latest'): # Secret Manager クライアントを作成する client = secretmanager.SecretManagerServiceClient() # シークレットのバージョンのリソース名を構築する project_id = os.getenv('GOOGLE_CLOUD_PROJECT') name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}" # シークレットのバージョンにアクセスする response = client.access_secret_version(name=name) # デコードされたシークレットを返す return response.payload.data.decode('UTF-8') EOF

    get_secret() 関数は、シークレット ID とオプションのバージョン ID を受け取ります。リクエストされたシークレットが関数から返されます。

Secret Manager を使用するように main.py を変更する

メインのコードファイルで Secret Manager を呼び出してシークレットを取得します。

  1. ファイル エディタで、ファイル ~/bookshelf/main.py を開きます。

  2. storage のインポートの後に、次の行を追加します。

    import secrets

    この行は、先ほど作成した secrets.py ファイルをインポートします。

  3. app.config.update 関数呼び出しに以下の SECRET_KEY があります。

    SECRET_KEY='secret', # 本番環境用アプリのコードに SECRET_KEY を保存しないでください

    これを、次のように変更します。

    SECRET_KEY=secrets.get_secret('flask-secret-key'),

    Flask 秘密鍵はアプリケーション コードに保存されなくなりました。

  4. ファイルを保存します。

タスク 4. OAuth フローの関数を作成する

このタスクでは、OAuth ログイン フローを管理する関数を追加します。

ユーザーがウェブ アプリケーションにログインすると、アプリは OAuth 認証シーケンスを開始します。OAuth では、ユーザーが認証を行い、アプリケーションが要求するアクセスに同意できます。OAuth 認証シーケンスは次のようになります。

認証シーケンスは、アプリケーションがブラウザを Google URL にリダイレクトしたときに開始されます。ユーザー認証、セッションの選択、ユーザーの同意は Google が処理します。認証コードが返され、アプリケーションはそれをアクセス トークンおよび更新トークンと交換できます。

アプリケーションは、更新トークンを今後使用するために保存し、アクセス トークンを使用して Google API にアクセスします。Bookshelf アプリケーションは、Google API を呼び出してユーザーに関する情報を取得します。アクセス トークンの有効期限が切れると、アプリケーションは更新トークンを使用して新しいアクセス トークンを取得します。

依存関係を追加する

Google 用の Python OAuth クライアントには、さらに 3 つの Python パッケージが必要です。

  1. ~/bookshelf/requirements.txt ファイルに次の行を追加します。

    google-api-python-client==2.101.0 google-auth==2.23.1 google-auth-oauthlib==1.1.0

    requirements.txt ファイルは次のようになります。

    Flask==2.3.3 gunicorn==21.2.0 google-cloud-logging==3.6.0 google-cloud-firestore==2.12.0 google-cloud-storage==2.10.0 google-cloud-secret-manager==2.16.4 google-api-python-client==2.101.0 google-auth==2.23.1 google-auth-oauthlib==1.1.0
  2. ファイルを保存します。

  3. 依存関係の更新バージョンをインストールするには、次のコマンドを実行します。

    pip3 install -r ~/bookshelf/requirements.txt --user

認証フローを管理する OAuth 関数を追加する

oauth.py ファイルには、Google から OAuth トークンを取得するコードが含まれています。

  1. oauth.py ファイルを作成するには、次のコマンドを実行します。

    cat > ~/bookshelf/oauth.py <<EOF import google.oauth2.credentials import google_auth_oauthlib.flow from uuid import uuid4 from googleapiclient.discovery import build from werkzeug.exceptions import Unauthorized def _credentials_to_dict(credentials): """ 認証情報マッピング(オブジェクト)をディクショナリに変換する。 """ return { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes, 'id_token': credentials.id_token, } def authorize(callback_uri, client_config, scopes): """ OAuth フローを開始するために Google へのリダイレクトに使用する URL を構築する。 """ # フロー構成の詳細を指定する flow = google_auth_oauthlib.flow.Flow.from_client_config( client_config=client_config, scopes=scopes, }) flow.redirect_uri = callback_uri # ランダムな状態を作成する state = str(uuid4()) # 認証 URL を取得する authorization_url, state = flow.authorization_url( # オフライン アクセスでは、ユーザーに再度プロンプトを表示せずにアクセス トークンを更新できる # ここでオンラインを使用して強制的にログインする access_type='online', state=state, prompt='consent', include_granted_scopes='false', }) return authorization_url, state def handle_callback(callback_uri, client_config, scopes, request_url, stored_state, received_state): """ リクエスト URL の認証コードを使用して認証情報を取得し、ログイン ユーザーのユーザー情報を取得する。 """ # 受け取った状態を検証する if received_state != stored_state: raise Unauthorized(f'Invalid state parameter: received={received_state} stored={stored_state}') # フロー構成の詳細を指定する flow = google_auth_oauthlib.flow.Flow.from_client_config( client_config=client_config, scopes=scopes ) flow.redirect_uri = callback_uri # リクエストの詳細を使用してトークンを取得する flow.fetch_token(authorization_response=request_url) credentials = flow.credentials oauth2_client = build('oauth2','v2',credentials=credentials, cache_discovery=False) user_info = oauth2_client.userinfo().get().execute() return _credentials_to_dict(credentials), user_info EOF

    authorize() 関数は、認証シーケンスを開始します。渡された client_config パラメータを使用してフローを構成します。このパラメータは、シークレットとして保存された OAuth 構成 JSON 文字列から構成されます。callback_uri は、Google が認証コードで呼び出す場所を指定しますこの URI は、Bookshelf アプリケーションの承認済みのリダイレクト URI として構成された URI と一致する必要があります。flow.authorization_url() 呼び出しは、Google へのリダイレクトの完全な URL を構築します。状態が作成されて渡された後、セッションに保存されて、この呼び出しと最終的なコールバックを一致させます。認証 URL と状態が呼び出し元に返されます。

    handle_callback() 関数は、Google からコールバックを受信したときに使用されます。コールバック URL で指定された状態は、認証 URL で送信された保存済み状態と一致している必要があります。その後、flow.fetch_token() 呼び出しを使用して、更新トークンやアクセス トークンなどの認証情報を取得できます。返された認証情報を使用して Google を呼び出し、ログイン ユーザーのユーザー情報を取得します。その後、認証情報とユーザー情報が呼び出し元に返されます。

    注: oauth2_client.userinfo() の行に、userinfo メンバーが存在しないことを示すエラー メッセージが IDE で表示されることがあります。Resource オブジェクトは、build() によって返され、有効なメンバーは、コンパイル時にわかりません。このエラーは無視してかまいません。

タスク 5. ログイン、コールバック、ログアウトのエンドポイントを追加する

このタスクでは、さきほど作成した OAuth 関数を使用して、ログイン、ログアウト、コールバックのエンドポイントを実装します。

HTML テンプレートを変更する

  1. エラー テンプレートを作成するには、次のコマンドを実行します。

    cat > ~/bookshelf/templates/error.html <<EOF {% extends "base.html" %} {% block content %} <h3>エラー: {{error_message}}</h3> {% endblock %} EOF

    ログイン時にエラーが発生することがあります。このページは、エラーを表示するために使用されます。

  2. ファイル エディタで、ファイル ~/bookshelf/templates/base.html を開きます。

    ログインとログアウトのリンクがアプリケーションに追加されます。

  3. navbar セクションで、class="nav navbar-nav" の順序なしリスト(ul)終了タグ(/ul)の次の行に、次のセクションを追加します。

    <ul class="nav navbar-nav navbar-right"> {% if session['credentials'] %} <div class="navbar-brand">{{session['user'].email}}</div> <div class="navbar-brand"><a href="/logout">ログアウト</a></div> {% else %} <div class="navbar-brand"><a href="/login">ログイン</a></div> {% endif %} </ul>

    ファイルは次のようになります。

    <!DOCTYPE html> <html lang="en"> <head> <title>Bookshelf</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> </head> <body> <div class="navbar navbar-default"> <div class="container"> <div class="navbar-header"> <div class="navbar-brand">Bookshelf</div> </div> <ul class="navbar-nav"> <li><a href="/">書籍</a></li> </ul> <ul class="nav navbar-nav navbar-right"> {% if session['credentials'] %} <div class="navbar-brand">{{session['user'].email}}</div> <div class="navbar-brand"><a href="/logout">ログアウト</a></div> {% else %} <div class="navbar-brand"><a href="/login">ログイン</a></div> {% endif %} </ul> </div> </div> <div class="container"> {% block content %}{% endblock %} </div> </body> </html>

    これで、ベース テンプレートでは、ユーザーがログインしているかどうかをセッションを使用して確認するようになります。ユーザーがログインしている場合は、ユーザーのメールアドレスとログアウト リンクが表示されます。ユーザーがログインしていない場合は、ログイン リンクが表示されます。

  4. ファイルを保存します。

インポートを変更する

  1. ファイル エディタで、ファイル ~/bookshelf/main.py を開きます。

  2. flask インポートに session を追加します

    flask のインポートは次のようになります。

    from flask import current_app, Flask, redirect, render_template from flask import request, url_for, session

    セッションは、ログイン ユーザーに関連付けられた情報へのアクセスを提供します。セッション データは Cookie に保存されます。

  3. cloud_logging import の行の後に、次の行を追加します。

    import json import os from urllib.parse import urlparse

    main.py では、json ライブラリを使用してクライアント シークレット文字列をマッピング(オブジェクト)に変換し、os ライブラリを使用して環境変数を使用します。urlparse() 関数を使用して、URL のスキームとホスト名を置き換えます。

  4. secrets のインポートの後に、次の行を追加します。

    import oauth

    これにより、作成した OAuth 関数がインポートされます。

構成項目を追加する

  1. app.config.update() 関数呼び出しで、ALLOWED_EXTENSIONS の行の後に次の行を追加します。

    CLIENT_SECRETS=json.loads(secrets.get_secret('bookshelf-client-secrets')), SCOPES=[ 'openid', 'https://www.googleapis.com/auth/contacts.readonly', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', ], EXTERNAL_HOST_URL=os.getenv('EXTERNAL_HOST_URL'),

    次の構成項目が追加されます。

    • CLIENT_SECRETS には、Secret Manager に保存された OAuth 構成のマッピング(オブジェクト)が含まれています。
    • SCOPES には、リクエストするスコープのリストが含まれます。
    • EXTERNAL_HOST_URL は、コールバック URL を決定するために使用されます。Cloud Shell で ウェブでプレビューを使用すると、localhost(127.0.0.1)ポート 80 で実行するように設定されたアプリケーションが https://8080-...-cloudshell.dev でインターネットに公開されます。この URL を使用して、コールバック エンドポイントの localhost URL を一般公開可能な URL に変換します。値は環境変数として渡されます。

エンドポイントとサポート関数を追加する

  1. log_request() 関数(先頭が def log_request():)の後に、次の関数を追加します。

    def logout_session(): """ 既知のセッション アイテムをクリアする。 """ session.pop('credentials', None) session.pop('user', None) session.pop('state', None) session.pop('error_message', None) session.pop('login_return', None) return def external_url(url): """ Cloud Shell で https://8080-***/ を http 経由で localhost にルーティングする この関数で localhost ホストを構成済みのスキームとホスト名に置き換える """ external_host_url = current_app.config['EXTERNAL_HOST_URL'] if external_host_url is None: # force https if url.startswith('http://'): url = f"https://{url[7:]}" return url # スキームとホスト名を外部ホスト URL に置き換える parsed_url = urlparse(url) replace_string = f"{parsed_url.scheme}://{parsed_url.netloc}" new_url = f"{external_host_url}{url[len(replace_string):]}" return new_url @app.route('/error') def error(): """ エラーを表示する。 """ log_request(request) if "error_message" not in session: return redirect(url_for('.list')) # レンダリング エラー return render_template('error.html', error_message=session.pop('error_message', None)) @app.route("/login") def login(): """ ログインしていない場合はログインする。 """ log_request(request) if not "credentials" in session: # ログインが必要 current_app.logger.info('logging in') # 認証 URLを取得する authorization_url, state = oauth.authorize( callback_uri=external_url(url_for('oauth2callback', _external=True)), client_config=current_app.config['CLIENT_SECRETS'], scopes=current_app.config['SCOPES']) current_app.logger.info(f"authorization_url={authorization_url}") # コールバックの検証のために状態を保存する session['state'] = state return redirect(authorization_url) # ログイン済み return redirect(session.pop('login_return', url_for('.list'))) @app.route("/oauth2callback") def oauth2callback(): """ OAuth プロセス時のコールバックの宛先。""" log_request(request) # エラーについて確認。ユーザーによるアクセス拒否の可能性。 error = request.args.get('error', None) if error: session['error_message'] = f"{error}" return redirect(url_for('.error')) # OAuth2 コールバックを処理 credentials, user_info = oauth.handle_callback( callback_uri=external_url(url_for('oauth2callback', _external=True)), client_config=current_app.config['CLIENT_SECRETS'], scopes=current_app.config['SCOPES'], request_url=external_url(request.url), stored_state=session.pop('state', None), received_state=request.args.get('state', '')) session['credentials'] = credentials session['user'] = user_info current_app.logger.info(f"user_info={user_info}") return redirect(session.pop('login_return', url_for('.list'))) @app.route("/logout") def logout(): """ ログアウトしてルート ページに戻る。 """ log_request(request) logout_session() return redirect(url_for('.list'))

    logout_session() 関数は、既知のセッション エントリをクリアします。

    external_url() 関数は、URL のスキームとホスト名を、外部アクセス用の別のホスト名に置き換えます。置き換えるホスト名を指定しない場合、関数は、返される URL が https を使用していることを確認します。

    /error エンドポイントは、エラーを表示するために使用されます。

    /login エンドポイントは、ユーザーがログインしているかどうかをセッションで確認します。セッションに認証情報が保存されている場合、ユーザーはログインしています。ユーザーがログインしていない場合は、oauth.authorize() が呼び出されて、Google へのリダイレクト用の認証 URL と状態が取得されます。状態がセッションに保存され、ブラウザが認証 URL にリダイレクトされます。

    /oauth2callback エンドポイントは、認証プロセス中に Google によって呼び出されます。エラーが発生した場合、プロセスは失敗し、ユーザーはエラーページにリダイレクトされます。エラーでなければ、handle_callback() が呼び出され、トークンとユーザー情報が取得されます。プロセスの終了時に、ユーザーはログインが自動的に開始された前のページにリダイレクトされます。戻る場所がない場合、ルートページ(書籍リスト)にリダイレクトされます。

    /logout エンドポイントは、セッションから認証情報とユーザーデータを削除してユーザーをログアウトさせ、ルートページに戻ります。

書籍の追加、編集、削除時にログインを強制する

ユーザーはログインせずに、bookshelf の書籍を閲覧できます。しかし、ユーザーがなんらかの方法で書籍を変更する前にログインすることをユーザーに強制するのが適切です。

ユーザーがログインしていない状態で書籍を追加、編集、削除しようとすると、ログインが強制されるようにする必要があります。

  1. add() 関数で、log_request() の呼び出しの直後に次の行を追加します。

    # 「認証情報」がセッションにない場合は ログイン済みである必要がある: session['login_return'] = url_for('.add') return redirect(url_for('.login'))

    add() では、ユーザーがログインしていない場合、ログイン後に追加ページに戻ります。

  2. edit() 関数で、log_request() の呼び出しの直後に次の行を追加します。

    # 「認証情報」がセッションにない場合は ログイン済みである必要がある: session['login_return'] = url_for('.edit', book_id=book_id) return redirect(url_for('.login'))

    edit() では、ユーザーがログインしていない場合、ログイン後にこの書籍の編集ページに戻ります。

  3. delete() 関数で、log_request() の呼び出しの直後に次の行を追加します。

    # 「認証情報」がセッションにない場合は ログイン済みである必要がある: session['login_return'] = url_for('.view', book_id=book_id) return redirect(url_for('.login'))

    delete() では、ユーザーがログインしていない場合、ログイン後にこの書籍の表示ページに戻ります。

  4. ファイルを保存します。

アプリケーションをテストする

  1. HTTP サーバーを起動するには、Cloud Shell で次のコマンドを実行します。

    cd ~/bookshelf; EXTERNAL_HOST_URL="https://8080-$WEB_HOST" ~/.local/bin/gunicorn -b :8080 main:app

    次の環境変数がアプリケーションに渡されます。

    • EXTERNAL_HOST_URL は、コールバック URL で使用する必要があるスキームとホスト名を指定します。この環境変数が指定されていない場合、認証 URL で Google に渡される redirect_uri には、受信 URL でアプリケーションが認識するホスト名(localhost である 127.0.0.1:8080)が使用されます。ウェブでプレビューは、cloudshell.dev URL からのリクエストを localhost(http://127.0.0.1:8080)に転送します。
    注: Cloud Shell の承認を求められた場合は、[承認] をクリックします。
  2. ウェブブラウザでアプリケーションを開くには、[ウェブでプレビュー] をクリックし、[ポート 8080 でプレビュー] を選択します。

    ブラウザで新しいタブが開き、アプリケーションが実行されます。「オズの魔法使い」の書籍が表示されます。ユーザーはログインしていません。

  3. [+ 書籍の追加] をクリックします。

    書籍を追加するにはログインする必要があるため、Google でログインするためのアカウントを選択するよう求められます。

  4. 受講者のメールアドレスをクリックし、[続行] をクリックします。

    今後、Google は、リクエストされた制限付きスコープまたはセンシティブでないスコープについて同意を取得します。この場合、すべての連絡先のダウンロードはプライベート データにかかわるスコープです。

  5. [許可] をクリックします。

    アプリケーションの [書籍の追加] ページに戻ります。ログイン済みの状態で、右上にはメールアドレスが表示されます。Cloud Shell でログを見ると、Google からのコールバック呼び出しが表示されます。

    INFO:main:REQ: GET http://127.0.0.1:8080/oauth2callback?state=88789b07-2474-423f-b572-f5d4a3240ace&code=4g0AfJohXm0vtB2eYHnRaAeM8m-VCmnssg5YgrjoJstTLmHaVq8nlbJo5uzIS67NbWTXTOqDw&scope=email%20profile%20openid%20https://www.googleapis.com/auth/contacts.readonly%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&authuser=0&hd=qwiklabs.net&prompt=consent

    ユーザーがアクセスに同意したため、code という名前のパラメータに認証コードが格納され、その後認証情報と交換されます。許可されたスコープも返されます。

  6. [書籍] をクリックし、[+ 書籍の追加] をクリックします。

    すでにログイン済みなので、[書籍の追加] ページに直接移動できます。

  7. [ログアウト] をクリックし、[ログイン] をクリックします。

  8. 受講者のメールアドレスをクリックし、[続行] をクリックしてから、[キャンセル] をクリックします。

    エラーページに戻ります。Cloud Shell でログを確認します。Google から次のような内容のコールバックが返されます。

    INFO:main:REQ: GET http://127.0.0.1:8080/oauth2callback?error=access_denied&state=72342071-c8dc-43be-8184-9f6bd6069cd5

    この場合、同意が提供されていないため、認証コードは返されず、アプリケーションはユーザーの認証情報を取得できません。

  9. Cloud Shell でアプリケーションを終了するには、Ctrl+C キーを押します。

[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。 ログイン、コールバック、ログアウトのエンドポイントを追加する

タスク 6. 翻訳の関数を作成する

このタスクでは、テキストの言語を検出し、テキストを翻訳する Cloud Translation API を使用する関数を作成します。

Cloud Translation API への呼び出しでは、アプリケーションの認証情報が使用されます。

Cloud Translation の依存関係を追加する

アプリケーションには別の Python パッケージが必要です。

  1. ~/bookshelf/requirements.txt ファイルに次の行を追加します。

    google-cloud-translate==3.12.0

    requirements.txt ファイルは次のようになります。

    Flask==2.3.3 gunicorn==23.0.0 google-cloud-logging==3.6.0 google-cloud-firestore==2.12.0 google-cloud-storage==2.10.0 google-cloud-secret-manager==2.16.4 google-api-python-client==2.101.0 google-auth==2.23.1 google-auth-oauthlib==1.1.0 google-cloud-translate==3.12.0
  2. ファイルを保存します。

  3. 更新された依存関係をインストールするには、次のコマンドを実行します。

    pip3 install -r ~/bookshelf/requirements.txt --user

翻訳関数を追加する

translate.py ファイルには、翻訳を実行するコードが含まれています。

  1. translate.py ファイルを作成するには、次のコマンドを実行します。

    cat > ~/bookshelf/translate.py <<EOF import os from google.cloud import translate PROJECT_ID = os.getenv('GOOGLE_CLOUD_PROJECT') PARENT = f"projects/{PROJECT_ID}" supported_languages = None def get_languages(): """ サポートされている言語のリストを取得する。 """ # グローバル変数を使用する global supported_languages # サポートされている言語を取得する(以前に取得していない場合) if not supported_languages: client = translate.TranslationServiceClient() response = client.get_supported_languages( parent=PARENT, display_language_code='en', ) supported_languages = response.languages return supported_languages def detect_language(text): """ 入力されたテキストの言語を検出する。 最も可能性の高い言語を返す。 """ client = translate.TranslationServiceClient() response = client.detect_language( parent=PARENT, content=text, ) return response.languages[0] def translate_text(text, target_language_code): """ テキストをターゲット言語に翻訳する。 """ client = translate.TranslationServiceClient() response = client.translate_text( parent=PARENT, contents=[text], target_language_code=target_language_code, ) return response.translations[0] EOF

    get_languages() 関数は、Cloud Translation API でサポートされている言語のリストを取得します。リストの各言語には、ID(language_code)と表示テキスト(display_name)が含まれます。

    detect_language() 関数は、テキスト文字列の言語を検出します。

    translate_language() 関数は、テキストを指定された言語に翻訳します。

タスク 7. 言語選択のためのユーザー プロファイルを作成し、説明を翻訳する

このタスクでは、ログイン ユーザーのユーザー プロファイルを作成します。ユーザーの設定言語を選択できます。

プロファイルは、profiles という名前の Firestore コレクションに保存されます。ユーザーがプロファイルを更新するまで、英語を設定言語とするデフォルトのプロファイルが使用されます。

プロファイルの読み取りと更新を行う関数を追加する

profiledb.py ファイルには、ユーザー プロファイルを読み取り、更新するコードが含まれています。ユーザーのメールアドレスがプロファイル キーとして使用されます。この実装では、プロファイルに含まれる項目は設定言語のみです。

  1. profiledb.py ファイルを作成するには、次のコマンドを実行します。

    cat > ~/bookshelf/profiledb.py <<EOF from google.cloud import firestore default_profile = { "preferredLanguage": "en" } def __document_to_dict(doc): if not doc.exists: return None doc_dict = doc.to_dict() doc_dict['id'] = doc.id return doc_dict def read(email): """ メールでプロファイルを返す。 """ db = firestore.Client() # ID でデータベースからプロファイルを取得する profile_ref = db.collection("profiles").document(email) profile_dict = __document_to_dict(profile_ref.get()) # プロファイルが存在しない場合は空のディクショナリを返す if profile_dict is None: profile_dict = default_profile.copy() return profile_dict def read_entry(email, key, default_value=''): """ メールアドレスとキーでプロファイルのエントリを返す。 """ profile_dict = read(email) return profile_dict.get(key, default_value) def update(data, email): """ プロファイルを更新し、更新したプロファイルの詳細を返す。 """ db = firestore.Client() # データベースのプロファイルを更新する profile_ref = db.collection("profiles").document(email) profile_ref.set(data) return __document_to_dict(profile_ref.get()) EOF

    read() 関数は、指定したユーザーのプロファイルを取得します。プロファイルが見つからない場合は、デフォルト プロファイルのコピーが返されます。

    read_entry() 関数は、ユーザーのプロファイルから単一の値を返します。ユーザーのプロファイルにキーが見つからない場合、渡されたデフォルト値が代わりに返されます。

    update() 関数は、指定されたデータを使用してユーザーのプロファイルを作成または上書きします。

ユーザー プロファイルの表示と編集のためにプロファイル エンドポイントを追加する

  1. profile.html にユーザー プロファイルの新しいテンプレートを作成するには、次のコマンドを実行します。

    cat > ~/bookshelf/templates/profile.html <<EOF {# [START form] #} {% extends "base.html" %} {% block content %} <h3>{{session['user']['email']} のプロファイル</h3> <form method="POST" enctype="multipart/form-data"> <div class="form-group"> <label for="preferredLanguage">設定言語</label> <select id="preferredLanguage" name="preferredLanguage"> {% for l in languages %} {% if l.language_code == profile['preferredLanguage'] %} <option value="{{l.language_code}}" selected>{{l.display_name}}</option> {% else %} <option value="{{l.language_code}}">{{l.display_name}}</option> {% endif %} {% endfor %} </select> </div> <button type="submit" class="btn btn-success">保存</button> </form> {% endblock %} {# [END form] #} EOF

    このテンプレートでは、選択コントロールと送信ボタンを含む 1 つのフォームを作成します。選択コントロールは、languages リスト変数を使用して渡されたすべての言語で読み込まれます。各エントリの値は language_code で、display_name は選択コントロールに表示されます。最初に表示される言語は、プロファイルで指定された preferredLanguage です。

  2. ファイル エディタで、ファイル ~/bookshelf/main.py を開きます。

  3. oauth のインポートの後に、次の行を追加します。

    import translate import profiledb

    これにより、先ほど作成した translate.py ファイルと profiledb.py ファイルがインポートされます。

  4. /profile エンドポイントを追加するには、/books/<book_id>/delete エンドポイントの後に次の関数を追加します。

    @app.route('/profile', methods=['GET', 'POST']) def profile(): """ GET の場合、ユーザー プロファイルの更新された詳細情報を収集するためのフォームを表示する。 POST の場合、指定されたフォームに基づいてプロファイルを更新する。 """ log_request(request) # 「認証情報」がセッションにない場合は ログイン済みである必要がある: session['login_return'] = url_for('.profile') return redirect(url_for('.login')) # 既存のプロファイルを読み取る email = session['user']['email'] profile = profiledb.read(email) # フォームが送信された場合は詳細を保存する if request.method == 'POST': # フォームから書籍の詳細を取得する data = request.form.to_dict(flat=True) # プロファイルを更新する profiledb.update(data, email) session['preferred_language'] = data['preferredLanguage'] # ルートに戻る return redirect(url_for('.list')) # 書籍を更新するためのフォームをレンダリングする return render_template('profile.html', action='Edit', profile=profile, languages=translate.get_languages())

    プロファイルにはログイン ユーザーのみがアクセスできるため、ログインしていないユーザーはログイン画面にリダイレクトされます。

    ログイン ユーザーのメールアドレスはセッションのユーザー情報から取得され、現在のプロファイルが読み取られます。

    プロファイルは、profile.html テンプレートを使用してレンダリングされます

    送信ボタンをクリックすると、データベースでプロファイルが更新され、ユーザーの設定言語がセッションに保存され、ブラウザがルートページにリダイレクトされます。

  5. ファイルを保存します。

ユーザーのメールアドレスをクリックした時にプロファイルに移動する

  1. ファイル エディタで、ファイル ~/bookshelf/templates/base.html を開きます。

  2. このファイルで、次の行を変更します。

    <div class="navbar-brand">{{session['user'].email}}</div>

    これを、次のように変更します。

    <div class="navbar-brand"><a href="/profile">{{session['user'].email}}</a></div>

    これにより、表示されるメールアドレスが、/profile エンドポイントにリダイレクトするクリック可能なリンクに変わります。

  3. ファイルを保存します。

表示ページの説明を翻訳する

  1. ファイル エディタで、ファイル ~/bookshelf/templates/view.html を開きます。

  2. このファイルで、次の行を変更します。

    <p class="book-description">{{book.description}}</p>

    これを、次のように変更します。

    {% if translation_language is not none %} <p class="book-description"><strong>説明({{description_language}}): </strong>{{book.description}}</p> <p class="book-description"><strong>翻訳({{translation_language}}): </strong>{{translated_text}}</p> {% else %} <p class="book-description"><strong>説明: </strong>{{book.description}}</p> {% endif %}

    translation_language が指定されていない場合は、説明は変更されません。ただし、翻訳言語がある場合は、元の説明の言語が表示され、次の行に翻訳されたテキストが表示されます。ビュー エンドポイントはこの追加情報を渡す必要があります。

  3. ファイルを保存します。

  4. ファイル エディタで、ファイル ~/bookshelf/main.py を開きます。

  5. log_request() 関数(先頭が def log_request():)の後に、次のコードを追加します。

    # 言語コードと表示名のマッピングを構築する display_languages = {} for l in translate.get_languages(): display_languages[l.language_code] = l.display_name

    detect_language() 関数は検出された言語コードを返しますが、表示名は返しませこのコードは、言語コードから表示名へのマッピングを作成します。検出された言語をビュー テンプレートに表示するために使用されます。

  6. ビュー エンドポイント全体のコードを次のコードに置き換えます。

    @app.route('/books/<book_id>') def view(book_id): """ 指定した書籍の詳細を表示する。 """ log_request(request) # 特定の書籍を取得する book = booksdb.read(book_id) current_app.logger.info(f"book={book}") # ログアウトした場合のデフォルト description_language = None translation_language = None translated_text = '' if book['description'] and "credentials" in session: preferred_language = session.get('preferred_language', 'en') # 説明を翻訳する translation = translate.translate_text( text=book['description'], target_language_code=preferred_language, ) description_language = display_languages[translation.detected_language_code] translation_language = display_languages[preferred_language] translated_text = translation.translated_text # 書籍の詳細をレンダリングする return render_template('view.html', book=book, translated_text=translated_text, description_language=description_language, translation_language=translation_language, )

    このコードにより、書籍の説明がユーザーの設定言語に翻訳され、翻訳と言語がテンプレートに渡されます。

  7. ファイルを保存します。

タスク 8. アプリケーションをテストする

  1. HTTP サーバーを起動するには、次のコマンドを実行します。

    cd ~/bookshelf; EXTERNAL_HOST_URL="https://8080-$WEB_HOST" ~/.local/bin/gunicorn -b :8080 main:app
  2. ウェブブラウザでアプリケーションを開くには、[ウェブでプレビュー] をクリックし、[ポート 8080 でプレビュー] を選択します。

    ブラウザで新しいタブが開き、アプリケーションが実行されます。「オズの魔法使い」の書籍が表示されます。

    注: Cloud Shell を承認するよう求められたら、[承認] をクリックします。
  3. ユーザーがログインしていない場合は、[ログイン] をクリックし、同意してユーザーをログインさせます。

    メールアドレスがリンクになります。

  4. メールアドレスをクリックします。

    プロファイルが表示されます。言語選択コントロールに「English」と表示されます。

  5. [設定言語] を [スワヒリ語] に変更し、[保存] をクリックします。

  6. 「オズの魔法使い」の書籍をクリックします。

    表示ページには、元の英語の説明とスワヒリ語の翻訳の両方が表示されます。

[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。 アプリケーションをテストする

お疲れさまでした

ユーザーのログインに OAuth を使用するようにアプリケーションを変更できました。次に、設定言語を含むユーザー プロファイルを追加しました。また、Cloud Translation API を使用して、書籍の説明の翻訳を提供しました。

次のステップと詳細情報

ラボを終了する

ラボが完了したら、[ラボを終了] をクリックします。ラボで使用したリソースが Google Cloud Skills Boost から削除され、アカウントの情報も消去されます。

ラボの評価を求めるダイアログが表示されたら、星の数を選択してコメントを入力し、[送信] をクリックします。

星の数は、それぞれ次の評価を表します。

  • 星 1 つ = 非常に不満
  • 星 2 つ = 不満
  • 星 3 つ = どちらともいえない
  • 星 4 つ = 満足
  • 星 5 つ = 非常に満足

フィードバックを送信しない場合は、ダイアログ ボックスを閉じてください。

フィードバックやご提案の送信、修正が必要な箇所をご報告いただく際は、[サポート] タブをご利用ください。

Copyright 2024 Google LLC All rights reserved. Google および Google のロゴは、Google LLC の商標です。その他すべての社名および製品名は、それぞれ該当する企業の商標である可能性があります。

前へ 次へ

始める前に

  1. ラボでは、Google Cloud プロジェクトとリソースを一定の時間利用します
  2. ラボには時間制限があり、一時停止機能はありません。ラボを終了した場合は、最初からやり直す必要があります。
  3. 画面左上の [ラボを開始] をクリックして開始します

このコンテンツは現在ご利用いただけません

利用可能になりましたら、メールでお知らせいたします

ありがとうございます。

利用可能になりましたら、メールでご連絡いたします

1 回に 1 つのラボ

既存のラボをすべて終了して、このラボを開始することを確認してください

シークレット ブラウジングを使用してラボを実行する

このラボの実行には、シークレット モードまたはシークレット ブラウジング ウィンドウを使用してください。これにより、個人アカウントと受講者アカウントの競合を防ぎ、個人アカウントに追加料金が発生することを防ぎます。
プレビュー