[Keystone] リレーションシップの作成

リレーションシップの作成

2 つのコンテンツ タイプを相互に接続する方法と、管理 UI でこれらの接続を行う方法を構成する方法を学びます。

Keystone のインストール

Keystone ブログプロジェクトを立ち上げ、データベースと user リストを使用して実行しました。
keystone.ts

import { config, list } from '@keystone-6/core';
import { allowAll } from '@keystone-6/core/access';
import { text } from '@keystone-6/core/fields';

export default config({
  db: {
    provider: 'sqlite',
    url: 'file:./keystone.db',
  },
  lists: {
    User: list({
      access: allowAll,
      fields: {
        name: text({ validation: { isRequired: true } }),
        email: text({ validation: { isRequired: true }, isIndexed: 'unique' }),
      },
    }),
  },
});

投稿リストタイプを作成し、関係フィールドでユーザーに接続します。

Lists オブジェクトを作成する

タイプのフィールドを定義する前に post、リストを独自のオブジェクトに引き出して、先に進むことについて簡単に推論できるようにしましょう。
keystone.ts

import { config, list } from '@keystone-6/core';
import { allowAll } from '@keystone-6/core/access';
import { text } from '@keystone-6/core/fields';

const lists = {
  User: list({
    access: allowAll,
    fields: {
      name: text({ validation: { isRequired: true } }),
      email: text({ validation: { isRequired: true }, isIndexed: 'unique' }),
    },
  }),
};

export default config({
  db: {
    provider: 'sqlite',
    url: 'file:./keystone.db',
  },
  lists,
});

投稿リストを作成する

投稿タイプを作成するために、lists オブジェクトに Post キーを追加します。まず、投稿の title のための別の text フィールドを追加しましょう。
keystone.ts

...
const lists = {
  User: list({
    access: allowAll,
    fields: {
      name: text({ validation: { isRequired: true } }),
      email: text({ validation: { isRequired: true }, isIndexed: 'unique' }),
    },
  }),
  Post: list({
    access: allowAll,
    fields: {
      title: text(),
    },
  }),
};
...

これが機能することを確認しましょう。

投稿でユーザーをつなぐ

2 つのリストができたので、それらの間に関係を作成しましょう。
投稿は 1 人のユーザーにのみ関連付けることができますが、ユーザーは多数の投稿を持つことができるとします。この関係を作成するには、相互の関係を定義する関係フィールドを各リストに追加します。
keystone.ts

import { config, list } from '@keystone-6/core';
import { allowAll } from '@keystone-6/core/access';
import { text, relationship } from '@keystone-6/core/fields';

const lists = {
  User: list({
    access: allowAll,
    fields: {
      name: text({ validation: { isRequired: true } }),
      email: text({ validation: { isRequired: true }, isIndexed: 'unique' }),
      posts: relationship({ ref: 'Post.author', many: true }),
    },
  }),
  Post: list({
    access: allowAll,
    fields: {
      title: text(),
      author: relationship({ ref: 'User.posts' }),
    },
  }),
};
...

relationship は、関連付けるリストの field の名前を参照し、双方向にするために使用されます。つまり、author フィールドは User.posts に関連付けられ、一方で、posts フィールドは Post.author に関連付けられます。

フィールドの外観を構成する

現在のスキーマでは、author フィールドは選択肢入力を提供して、ユーザーを投稿に接続します。これは、このフィールドタイプのデフォルトの displayMode です。
Keystone では、フィールドの ui オプションを使用して、この表示を必要に応じて変更できます。各フィールドには、さまざまな ui オプションが用意されており、探索できます。author フィールドでは、管理 UI ユーザーの編集体験を改善するためにいくつかの変更を加えます。
keystone.ts

...
Post: list({
  access: allowAll,
  fields: {
    title: text(),
    author: relationship({
      ref: 'User.posts',
      ui: {
        displayMode: 'cards',
        cardFields: ['name', 'email'],
        inlineEdit: { fields: ['name', 'email'] },
        linkToItem: true,
        inlineCreate: { fields: ['name', 'email'] },
      },
    }),
  },
}),
...

設定を少し追加することで、ユーザー データを投稿フォームで直接変更できる、非常に異なる編集エクスペリエンスを作成しました。

リレーションシップの作成

アプリには、タイトルと著者フィールドを介したユーザーへのリンクがある新しい投稿リストがあります。カード UI 表示モードを使用して、インラインで編集できます。管理 UI エディターは、ユーザーフォームからも投稿を作成でき、双方向の関係があります。
keystone.ts

import { config, list } from '@keystone-6/core';
import { allowAll } from '@keystone-6/core/access';
import { text, relationship } from '@keystone-6/core/fields';

const lists = {
  User: list({
    access: allowAll,
    fields: {
      name: text({ validation: { isRequired: true } }),
      email: text({ validation: { isRequired: true }, isIndexed: 'unique' }),
      posts: relationship({ ref: 'Post.author', many: true }),
    },
  }),
  Post: list({
    access: allowAll,
    fields: {
      title: text(),
      author: relationship({
        ref: 'User.posts',
        ui: {
          displayMode: 'cards',
          cardFields: ['name', 'email'],
          inlineEdit: { fields: ['name', 'email'] },
          linkToItem: true,
          inlineCreate: { fields: ['name', 'email'] },
        },
      }),
    },
  }),
};

export default config({
  db: {
    provider: 'sqlite',
    url: 'file:./keystone.db',
  },
  lists,
});