Nuxt&Django REST FrameworkでCRUD GET編②


概要

フロント:Nuxt
バックエンド:Django REST Framework(以下DRF)
で新しいプロジェクトなどを立ち上げた時に設定などをいちいち調べるのがめんどくさくなったため、まとめておきます。

ただ、設定ファイルだけを書くのでは個人的に記事として物足りない。

なので、ついでに基本的な操作であるAPIを叩いてCRUDを行い、会員登録を実装するところまで書く予定です。
なお、今回はDBはSQLiteを使います。PostgreSQLやMySQLなど他のRDBが使いたい場合はDRF側のDBの設定を書きかえるだけなので、そちらの設定は各自よろしくお願いいたします。

この記事では、NuxtからDRFで作ったAPIを叩いてデータベースのから情報を取得、詳細な情報をクライアントサイドで表示させるところまでです。

ソースコードはこちらにあるのでわからないところは適宜見てください。

また、Twitterかこの記事のコメント欄でわからないところを聞いていただけると答えられます。

前回
Nuxt&Django REST FrameworkでCRUD GET編①

プロジェクト構成

前回はinspire.vueに直接コードを追加して商品欄も一覧を追加しました。
しかしこれでは少し見た目的によろしくないので細かな変更を加えていきます。

Nuxtではpages内のvueファイルの木構造によってvue-routerに沿った設定が自動生成されます。

Nuxtドキュメントの例にもあるように、ディレクトリ構造が以下の場合には、

pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue

自動的に以下が生成されます

router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users-id',
path: '/users/:id?',
component: 'pages/users/_id.vue'
},
{
name: 'slug',
path: '/:slug',
component: 'pages/_slug/index.vue'
},
{
name: 'slug-comments',
path: '/:slug/comments',
component: 'pages/_slug/comments.vue'
}
]
}

こういった仕様のため、ルーティングに関しての手間が省けるという利点があります。

したがって、まず新しくpagesの中にitemsフォルダを新しく作り、その中にitemのidに応じて詳細ページを作れるように_idフォルダを作ります。このようにフォルダの中に_idフォルダを作ることで取得したidに応じた情報を自動的にページを精製してくれるようになります。

Githubを見ながらこの辺りを進めるとわかりやすいかと思います。

そして、itemsフォルダにindex.vueを作り、以下のように前回書いたコードをロゴ抜きで移植し、

前回までは

でしたが、今回は

にアクセスしてみましょう。

items/index.vue
<template>
  <main class="container mt-5">
    <div class="row">
        <div class="col-12 text-right mb-4">
        <div class="d-flex justify-content-between">
          <h3>商品一覧</h3>
          <!-- <nuxt-link to="/items/add" class="btn btn-info">
            商品を追加する
          </nuxt-link> -->
        </div>
      </div>
      <template v-for="item in items">
        <div :key="item.id" class="col-lg-3 col-md-4 col-sm-6 mb-4">
          <!--<item-card :on-delete="deleteitem" :item="item" />-->
        </div>
      </template>
    </div>
    </main>
</template>

<script>
import ItemCard from '~/components/ItemCard.vue'

export default {
  components: {
    ItemCard
  },
  async asyncData ({ $axios, params }) {
    try {
      const items = await $axios.$get('items/')
      return { items }
    } catch (e) {
      return { items: [] }
    }
  },
  data () {
    return {
      items: []
    }
  },
  head () {
    return {
      title: '商品一覧'
    }
  }
}
</script>

するとこんな感じです。Vuetifyのロゴ入りの時よりもそれらしくなりましたね。

続いては詳細をクリックした時にきちんとそのページの説明文など詳細な説明が出るようにしましょう。
以下のように書いてみます。

items/_id/index.vue
<template>
  <main class="container my-5">
    <div class="row">
      <div class="col-12 text-center my-3">
        <h2 class="mb-3 display-4 text-uppercase">
          {{ item.name }}
        </h2>
      </div>
      <div class="col-md-6 mb-4">
        <img
          class="img-fluid"
          style="width: 400px; border-radius: 10px; box-shadow: 0 1rem 1rem rgba(0,0,0,.7);"
          :src="item.image"
          alt
        >
      </div>
      <div class="col-md-6">
        <div class="item-details">
          <h4>カテゴリー</h4>
          <p>{{ item.category }}</p>
          <h4>値段</h4>
          <p>{{ item.price }}</p>
          <h4>説明</h4>
          <p>{{ item.description }}</p>
        </div>
      </div>
    </div>
  </main>
</template>
<script>
export default {
  async asyncData ({ $axios, params }) {
    try {
      const item = await $axios.$get(`/items/${params.id}`)
      return { item }
    } catch (e) {
      return { item: [] }
    }
  },
  data () {
    return {
      item: {
      id:'',
      name:'',
      image:'',
      price:'',
      description:'',
      }
    }
  },
  head () {
    return {
      title: '商品詳細'
    }
  }
}
</script>
<style scoped>
</style>

そして詳細をクリックするとこんな感じです。

一覧のページでは読めなかった説明が読めますね。

こういった感じに商品一覧のページでは必要最低限の情報を取得し、各idごとのページではより詳細な情報を取得し、表示する、といったような使い分けをします。

詳細ページの作り方についてはこれくらいで終わりです。

次回はPOST編です。

※追記
書きました!
Nuxt&Django REST FrameworkでCRUD POST編