このチュートリアルでは、Azure Database for PostgreSQL 単一サーバーまたはフレキシブル サーバー データベースを静的 Web アプリに接続する方法について説明します。 構成しておくと、組み込みの /data-api エンドポイントに対して REST または GraphQL 要求を行うことで、バックエンド コードを記述しなくてもデータを操作できます。
わかりやすくするために、このチュートリアルでは、ローカル開発の目的で Azure データベースを使用する方法について説明しますが、ローカル開発のニーズにローカル データベース サーバーを使用することもできます。
Note
このチュートリアルでは、Azure Database for PostgreSQL フレキシブル サーバーまたは単一サーバーを使用する方法について説明します。 別のデータベースを使用する場合は、Azure Cosmos DB、Azure SQL、または MySQL のチュートリアルを参照してください。
このチュートリアルで学習する内容は次のとおりです。
- Azure Database for PostgreSQL フレキシブル サーバーまたは単一サーバー データベースを静的 Web アプリにリンクする
- データの作成、読み取り、更新、削除を行う
前提条件
このチュートリアルを完了するには、既存の Azure Database for PostgreSQL フレキシブル サーバーまたは単一サーバーと静的 Web アプリが必要です。 さらに、Visual Studio Code をインストールする必要があります。
| リソース | 説明 |
|---|---|
| Azure Database for PostgreSQL フレキシブル サーバーまたは Azure Database for PostgreSQL 単一サーバー データベース | まだ保持していない場合は、『Azure Database for PostgreSQL フレキシブル サーバー データベースを作成する』ガイド、または『Azure Database for PostgreSQL 単一サーバー データベースを作成する』ガイドの手順を実行します。 Static Web Apps のデータベース接続に接続文字列認証を使用する予定の場合は、PostgreSQL 認証を使用して Azure Database for PostgreSQL Server を作成してください。 この値は、後でマネージド ID を使用する場合、変更できます。 |
| 既存の静的 Web アプリ | まだない場合は、ファースト ステップ ガイドの手順に従って、"フレームワークなし" の静的 Web アプリを作成します。 |
| Visual Studio Code と PostgreSQL 拡張機能 | Visual Studio Code をまだインストールしていない場合は、ガイドに従って 、PostgreSQL 拡張機能を使用して Visual Studio Code をインストールします。 または、PgAdmin などの他のツールを使用して、PostgreSQL データベースに対してクエリを実行することもできます。 |
まず、Azure Static Web Apps データベース接続機能を使用するようにデータベースを構成します。
データベース接続を構成する
データベース接続を機能させるには、Azure Static Web Apps がデータベースにネットワーク アクセスできる必要があります。 さらに、Azure データベースをローカル開発に使用するには、独自の IP アドレスからの要求を許可するようにデータベースを構成する必要があります。
Azure portal で Azure Database for PostgreSQL サーバーに移動します。
Azure Database for PostgreSQL フレキシブル サーバーを使用している場合は、[設定] セクションで [ネットワーク] を選択します。 Azure Database for PostgreSQL 単一サーバーを使用している場合は、[設定] セクションで [接続のセキュリティ] を選択します。
ファイアウォール規則 セクションで、Add your current client IP address(現在のクライアント IP アドレスの追加) ボタンを選択します。 この手順により、このデータベースをローカル開発に使用できるようになります。
[ファイアウォール規則] セクションで [Azure 内の任意の Azure サービスにこのサーバーへのパブリック アクセスを許可する] チェックボックスをオンにします。 Azure Database for PostgreSQL 単一サーバーを使用している場合、このトグルのラベルは [Azure サービスへのアクセスを許可する] になります。 この手順により、デプロイされた Static Web Apps リソースがデータベースにアクセスできるようになります。
[保存] を選択します。
ローカル開発用のデータベース接続文字列を取得する
Azure データベースをローカル開発に使用するには、データベースの接続文字列を取得する必要があります。 ローカル データベースを開発目的で使用する予定の場合は、この手順を省略できます。
Azure portal で Azure Database for PostgreSQL サーバーに移動します。
[設定] セクションで、[接続文字列] を選択します。
[ADO.NET] ボックスから接続文字列をコピーし、テキスト エディターに貼り付けておきます。
接続文字列の
{your_password}プレースホルダーをパスワードに置き換えます。{your_database}プレースホルダーをデータベース名MyTestPersonDatabaseに置き換えます。 後の手順でMyTestPersonDatabaseを作成します。この接続文字列をローカル開発に使用するために、接続文字列に
Trust Server Certificate=True;を追加します。
サンプル データの作成
サンプル テーブルを作成し、チュートリアルと一致するサンプル データを使用してシード処理します。 このチュートリアルでは Visual Studio Code を使用しますが、PgAdmin やその他のツールを使用できます。
Visual Studio Code で、 Azure Database for PostgreSQL Server への接続を作成します
サーバーを右クリックし、[新しいクエリ] を選択します。 次のクエリを実行して、
MyTestPersonDatabaseという名前のデータベースを作成します。CREATE DATABASE "MyTestPersonDatabase";サーバーを右クリックし、[最新の情報に更新] を選択します。
MyTestPersonDatabaseを右クリックし、[新しいクエリ] を選択します。 次のクエリを実行して、MyTestPersonTableという名前の新しいテーブルを作成します。CREATE TABLE "MyTestPersonTable" ( "Id" SERIAL PRIMARY KEY, "Name" VARCHAR(25) NULL );次のクエリを実行して、MyTestPersonTable テーブルにデータを追加します。
INSERT INTO "MyTestPersonTable" ("Name") VALUES ('Sunny'); INSERT INTO "MyTestPersonTable" ("Name") VALUES ('Dheeraj');
静的 Web アプリを構成する
このチュートリアルの残りの部分では、ローカルでデータベース接続を使用するように静的 Web アプリのソース コードを編集することに重点を置いています。
重要
次の手順では、ファースト ステップ ガイドで作成した静的 Web アプリを使用していることを前提としています。 別のプロジェクトを使用している場合は、お使いのブランチ名と一致するように次の git コマンドを調整してください。
mainブランチに切り替えます。git checkout maingit pullを使用して、ローカル バージョンを GitHub 上のものと同期します。git pull origin main
データベース構成ファイルを作成する
次に、静的 Web アプリがデータベースとのインターフェイスに使用する構成ファイルを作成します。
ターミナルを開き、接続文字列を保持する新しい変数を作成します。 具体的な構文は、使用しているシェルの種類によって異なる場合があります。
export DATABASE_CONNECTION_STRING='<YOUR_CONNECTION_STRING>'<YOUR_CONNECTION_STRING>を、テキスト エディターに貼り付けておいた接続文字列の値に置き換えてください。npm を使用して、Static Web Apps CLI をインストールまたは更新します。 ご自分の状況に最も適したコマンドを選択します。
インストールするには、
npm installを使用します。npm install -g @azure/static-web-apps-clinpm install -g @azure/static-web-apps-cli更新するには、
npm updateを使用します。npm updatenpm updateswa db initコマンドを使用して、データベース構成ファイルを生成します。swa db init --database-type postgresqlinitコマンドは、swa-db-connections フォルダーに staticwebapp.database.config.json ファイルを作成します。このサンプルを、生成した staticwebapp.database.config.json ファイルに貼り付けます。
{
"$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json",
"data-source": {
"database-type": "postgresql",
"options": {
"set-session-context": false
},
"connection-string": "@env('DATABASE_CONNECTION_STRING')"
},
"runtime": {
"rest": {
"enabled": true,
"path": "/rest"
},
"graphql": {
"allow-introspection": true,
"enabled": true,
"path": "/graphql"
},
"host": {
"mode": "production",
"cors": {
"origins": ["http://localhost:4280"],
"allow-credentials": false
},
"authentication": {
"provider": "StaticWebApps"
}
}
},
"entities": {
"Person": {
"source": "MyTestPersonTable",
"permissions": [
{
"actions": ["*"],
"role": "anonymous"
}
]
}
}
}
次の手順に進む前に、構成ファイルのさまざまな側面について説明する次の表を確認してください。 構成ファイルと、項目レベルのセキュリティに関するリレーションシップやポリシーなどの機能の詳細な説明については、Data API Builder のドキュメントを参照してください。
| 特徴量 | 説明 |
|---|---|
| データベース接続 | 開発時に、ランタイムは、構成ファイル内の接続文字列の値から接続文字列を読み取ります。 接続文字列は構成ファイルに直接指定できますが、ベスト プラクティスは、接続文字列をローカル環境変数に格納することです。 構成ファイル内の環境変数の値は、@env('DATABASE_CONNECTION_STRING') 表記を介して参照できます。 接続文字列の値は、データベースを接続するときに収集された情報を使用して、デプロイされたサイトの Static Web Apps によって上書きされます。 |
| API エンドポイント | REST エンドポイントは、/data-api/rest を介して使用でき、GraphQL エンドポイントはこの構成ファイル内に構成されている /data-api/graphql を介して使用できます。 REST と GraphQL パスは構成できますが、/data-api プレフィックスは構成できません。 |
| API セキュリティ |
runtime.host.cors 設定を使用すると、API に対して要求を行うことができる許可された配信元を定義できます。 この場合、構成には開発環境が反映され、http://localhost:4280 の場所が許可リストに載せられます。 |
| エンティティ モデル | ルートを介して公開されるエンティティを REST API 内で定義するか、または GraphQL スキーマ内の種類として定義します。 この場合、Person という名前は、エンドポイントに公開される名前であり、entities.<NAME>.source は、データベース スキーマとテーブルのマッピングです。 API エンドポイント名がテーブル名と同じである必要がないことに注意してください。 |
| エンティティ セキュリティ |
entity.<NAME>.permissions 配列に一覧表示されているアクセス許可ルールは、エンティティの承認設定を制御します。
ロールを使用してルートをセキュリティで保護するのと同様に、ロールを使用してエンティティをセキュリティで保護することができます。 |
Note
構成ファイルの connection-string、host.mode、graphql.allow-introspection プロパティは、サイトをデプロイするときに上書きされます。 接続文字列は、Static Web Apps リソースにデータベースを接続するときに収集された認証の詳細で上書きされます。
host.mode プロパティが production に設定され、graphql.allow-introspection が false に設定されます。 これらのオーバーライドにより、開発と運用ワークロード全体で構成ファイルの一貫性が確保され、データベース接続が有効になっている Static Web Apps リソースがセキュリティで保護され、運用に対応できるようになります。
静的 Web アプリがデータベースに接続するように構成されたので、接続を確認できるようになりました。
ホーム ページの更新
index.html ファイル内の body タグ間のマークアップを、次の HTML に置き換えます。
<h1>Static Web Apps Database Connections</h1>
<blockquote>
Open the console in the browser developer tools to see the API responses.
</blockquote>
<div>
<button id="list" onclick="list()">List</button>
<button id="get" onclick="get()">Get</button>
<button id="update" onclick="update()">Update</button>
<button id="create" onclick="create()">Create</button>
<button id="delete" onclick="del()">Delete</button>
</div>
<script>
// add JavaScript here
</script>
ローカルでアプリケーションを起動する
Web サイトを実行し、データベース内のデータを直接操作することができるようになりました。
データベース構成を使用して静的 Web アプリを起動します。
swa start --data-api-location swa-db-connections
CLI が開始されたので、staticwebapp.database.config.json ファイルに定義されたエンドポイントを介してデータベースにアクセスできます。
http://localhost:4280/data-api/rest/<ENTITY_NAME> エンドポイントは、データベース内のデータを操作するための GET、PUT、POST、DELETE 要求を受け入れます。
http://localhost:4280/data-api/graphql エンドポイントは、GraphQL クエリとミューテーションを受け入れます。
データを操作する
フレームワークに依存しない次のコマンドは、データベースに対して完全な CRUD 操作を実行する方法を示しています。
各関数の出力がブラウザーのコンソール ウィンドウに表示されます。
CMD/CTRL + 、SHIFT + I キーの順に押下し、開発者ツールを開き、[コンソール] タブを選択します。
すべての項目を一覧表示する
index.html 内の script タグ間に次のコードを追加します。
async function list() {
const endpoint = '/data-api/rest/Person';
const response = await fetch(endpoint);
const data = await response.json();
console.table(data.value);
}
この例では、次のように記述されています。
-
fetchAPI の既定の要求では、動詞GETが使用されています。 - 応答ペイロード内のデータは、
valueプロパティにあります。
async function list() {
const query = `
{
people {
items {
Id
Name
}
}
}`;
const endpoint = "/data-api/graphql";
const response = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: query })
});
const result = await response.json();
console.table(result.data.people.items);
}
この例では、次のように記述されています。
- GraphQL クエリは、データベースから
IdフィールドとNameフィールドを選択します。 - サーバーに渡される要求には、
queryプロパティにクエリ定義が保持されているペイロードが必要です。 - 応答ペイロード内のデータは、
data.people.itemsプロパティにあります。
ページを更新し、[一覧表示] ボタンを選択します。
ブラウザーのコンソール ウィンドウに、データベース内のすべてのレコードを一覧表示するテーブルが表示されるようになりました。
| ID | Name |
|---|---|
| 1 | 晴れ |
| 2 | Dheeraj |
ブラウザーに表示される内容のスクリーンショットを次に示します。
ID で取得する
index.html 内の script タグ間に次のコードを追加します。
async function get() {
const id = 1;
const endpoint = `/data-api/rest/Person/Id`;
const response = await fetch(`${endpoint}/${id}`);
const result = await response.json();
console.table(result.value);
}
この例では、次のように記述されています。
- エンドポイントの後に
/person/Idが付きます。 - ID 値がエンドポイントの場所の末尾に追加されます。
- 応答ペイロード内のデータは、
valueプロパティにあります。
async function get() {
const id = 1;
const gql = `
query getById($id: Int!) {
person_by_pk(Id: $id) {
Id
Name
}
}`;
const query = {
query: gql,
variables: {
id: id,
},
};
const endpoint = "/data-api/graphql";
const response = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(query),
});
const result = await response.json();
console.table(result.data.person_by_pk);
}
この例では、次のように記述されています。
- GraphQL クエリは、データベースから
IdフィールドとNameフィールドを選択します。 - サーバーに渡される要求には、
queryプロパティにクエリ定義が保持されているペイロードが必要です。 - 応答ペイロード内のデータは、
data.person_by_pkプロパティにあります。
ページを更新し、[取得] ボタンを選択します。
ブラウザーのコンソール ウィンドウに、データベースから要求された 1 つのレコードを一覧表示するテーブルが表示されるようになりました。
| ID | Name |
|---|---|
| 1 | 晴れ |
更新プログラム
index.html 内の script タグ間に次のコードを追加します。
Static Web Apps では、PUT と PATCH の両方の動詞がサポートされます。
PUT 要求ではレコード全体が更新されますが、PATCH では部分的な更新が行われます。
async function update() {
const id = 1;
const data = {
Name: "Molly"
};
const endpoint = '/data-api/rest/Person/Id';
const response = await fetch(`${endpoint}/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
const result = await response.json();
console.table(result.value);
}
この例では、次のように記述されています。
- エンドポイントの後に
/person/Id/が付きます。 - ID 値がエンドポイントの場所の末尾に追加されます。
- REST 動詞は、データベース レコードを更新する
PUTです。 - 応答ペイロード内のデータは、
valueプロパティにあります。
async function update() {
const id = 1;
const data = {
Name: "Molly"
};
const gql = `
mutation update($id: Int!, $item: UpdatePersonInput!) {
updatePerson(Id: $id, item: $item) {
Id
Name
}
}`;
const query = {
query: gql,
variables: {
id: id,
item: data
}
};
const endpoint = "/data-api/graphql";
const res = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(query)
});
const result = await res.json();
console.table(result.data.updatePerson);
}
この例では、次のように記述されています。
- GraphQL クエリは、データベースから
IdフィールドとNameフィールドを選択します。 -
queryオブジェクトでは、GraphQL クエリがqueryプロパティ内に保持されます。 - GraphQL 関数への引数値は、
query.variablesプロパティを介して渡されます。 - サーバーに渡される要求には、
queryプロパティにクエリ定義が保持されているペイロードが必要です。 - 応答ペイロード内のデータは、
data.updatePersonプロパティにあります。
ページを更新し、[更新] ボタンを選択します。
ブラウザーのコンソール ウィンドウに、更新されたデータを示すテーブルが表示されるようになりました。
| ID | Name |
|---|---|
| 1 | Molly |
作成
index.html 内の script タグ間に次のコードを追加します。
async function create() {
const data = {
Name: "Pedro"
};
const endpoint = `/data-api/rest/Person/`;
const response = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
const result = await response.json();
console.table(result.value);
}
この例では、次のように記述されています。
- エンドポイントの後に
/person/が付きます。 - REST 動詞は、データベース レコードを追加する
POSTです。 - 応答ペイロード内のデータは、
valueプロパティにあります。
async function create() {
const data = {
Name: "Pedro"
};
const gql = `
mutation create($item: CreatePersonInput!) {
createPerson(item: $item) {
Id
Name
}
}`;
const query = {
query: gql,
variables: {
item: data
}
};
const endpoint = "/data-api/graphql";
const result = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(query)
});
const response = await result.json();
console.table(response.data.createPerson);
}
この例では、次のように記述されています。
- GraphQL クエリは、データベースから
IdフィールドとNameフィールドを選択します。 -
queryオブジェクトでは、GraphQL クエリがqueryプロパティ内に保持されます。 - GraphQL 関数への引数値は、
query.variablesプロパティを介して渡されます。 - サーバーに渡される要求には、
queryプロパティにクエリ定義が保持されているペイロードが必要です。 - 応答ペイロード内のデータは、
data.updatePersonプロパティにあります。
ページを更新し、[作成] ボタンを選択します。
ブラウザーのコンソール ウィンドウに、データベース内の新しいレコードを示すテーブルが表示されるようになりました。
| ID | Name |
|---|---|
| 3 | Pedro |
削除
index.html 内の script タグ間に次のコードを追加します。
async function del() {
const id = 3;
const endpoint = '/data-api/rest/Person/Id';
const response = await fetch(`${endpoint}/${id}`, {
method: "DELETE"
});
if(response.ok) {
console.log(`Record deleted: ${ id }`)
} else {
console.log(response);
}
}
この例では、次のように記述されています。
- エンドポイントの後に
/person/Id/が付きます。 - ID 値がエンドポイントの場所の末尾に追加されます。
- REST 動詞は、データベース レコードを削除する
DELETEです。 - 削除が成功した場合、応答ペイロードの
okプロパティはtrueです。
async function del() {
const id = 3;
const gql = `
mutation del($id: Int!) {
deletePerson(Id: $id) {
Id
}
}`;
const query = {
query: gql,
variables: {
id: id
}
};
const endpoint = "/data-api/graphql";
const response = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(query)
});
const result = await response.json();
console.log(`Record deleted: ${ result.data.deletePerson.Id }`);
}
この例では、次のように記述されています。
- GraphQL クエリで、データベースから
Idフィールドが選択されます。 -
queryオブジェクトでは、GraphQL クエリがqueryプロパティ内に保持されます。 - GraphQL 関数への引数値は、
query.variablesプロパティを介して渡されます。 - サーバーに渡される要求には、
queryプロパティにクエリ定義が保持されているペイロードが必要です。 - 応答ペイロード内のデータは、
data.deletePersonプロパティにあります。
ページを更新し、[削除] ボタンを選択します。
ブラウザーのコンソール ウィンドウに、削除要求からの応答を示すテーブルが表示されるようになりました。
削除されたレコード: 3
ローカルでサイトを操作したので、Azure にデプロイできるようになりました。
サイトのデプロイ
このサイトを運用環境にデプロイするには、構成ファイルをコミットし、変更をサーバーにプッシュするだけです。
追跡するファイルの変更を追加します。
git add .構成の変更をコミットします。
git commit -am "Add database configuration"変更をサーバーにプッシュします。
git push origin main
静的 Web アプリにデータベースを接続する
サイトの Static Web Apps インスタンスとデータベースの間の接続を作成するには、次の手順に従います。
Azure portal で静的 Web アプリを開く
[設定] セクションで、[データベース接続] を選択します。
[運用] セクションで、[既存のデータベースのリンク] リンクを選択します。
[既存のデータベースのリンク] ウィンドウで、次の値を入力します。
プロパティ 価値 データベースの種類 ドロップダウン リストからデータベースの種類を選択します。 サブスクリプション ドロップダウン リストから Azure サブスクリプションを選択します。 リソース名 目的のデータベースを含むデータベース サーバー名を選択します。 データベース名 静的 Web アプリにリンクするデータベースの名前を選択します。 認証の種類 [接続文字列] を選択しPostgreSQL のユーザー名とパスワードを入力します。 PostgreSQL 単一サーバーの場合は、 @servernameサフィックスを含めないでください。[OK]を選択します。
データベースが Static Web Apps リソースに接続されていることを確認する
静的 Web アプリにデータベースを接続し、サイトの構築が完了したら、次の手順に従ってデータベース接続を確認します。
Azure portal で静的 Web アプリを開く
[要点] セクションで、Static Web Apps リソースの [URL] を選択して、静的 Web アプリに移動します。
[一覧表示] ボタンを選択して、すべての項目を一覧表示します。
出力は、こちらのスクリーンショットのようになります。
リソースをクリーンアップする
このチュートリアルで作成したリソースを削除する場合は、データベースのリンクを解除し、サンプル データを削除する必要があります。
データベースのリンク解除: Azure portal で静的 Web アプリを開きます。 [設定] セクションで、[データベース接続] を選択します。 リンクされたデータベースの横で、[詳細の表示] を選択します。 [データベース接続の詳細] ウィンドウで、[リンク解除] ボタンを選択します。
サンプル データの削除: データベースで、
MyTestPersonTableという名前のテーブルを削除します。