๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
โญ Personal_Study/Vue

Vue with DRF

by ํฌ์ŠคํŠธ์‰์ดํฌ 2022. 11. 21.

Vue with DRF

Article Read

  1. ์‘๋‹ต ๋ฐ›์€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ํ™•์ธ

โœ” dataArray์— ๊ฐ ๊ฒŒ์‹œ๊ธ€ ๊ฐ์ฒด
โœ” ๊ฐ ๊ฒŒ์‹œ๊ธ€ ๊ฐ์ฒด๋Š” id, title, content๋กœ ๊ตฌ์„ฑ

  1. store/index.js ์ˆ˜์ •
// store/index.js

export default new Vuex.Store({
  state: {
    articles: [],
  },
  getters: {
  },
  mutations: {
    GET_ARTICLES(state, articles) {
      state.articles=articles
    }
  },
  actions: {
    getArticles(context) {
      axios({
        method: 'get',
        url: `${API_URL}/api/v1/articles/`
      })
        .then((res) => {
          // console.log(res, context)
          context.commit('GET_ARTICLES', res.data)
        })
        .catch((err) => {
          console.log(err)
        })
    }
})
  1. ๊ฒฐ๊ณผ ํ™•์ธ

Article Create

  1. views/CreateView.vue ์ฝ”๋“œ ํ™•์ธ
// views/CreateView.vue

<template>
  <div>
    <h1>๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ</h1>
    <form @submit.prevent='createArticle'>
      <label for="title">์ œ๋ชฉ : </label>
      <input type="text" id="title" v-model.trim="title"><br>
      <label for="content">๋‚ด์šฉ : </label>
      <textarea id="content" cols="30" rows="10" v-model="content"></textarea><br>
      <input type="submit" id="submit">
    </form>
  </div>
</template>

โœ” v-model.trim์„ ํ™œ์šฉํ•ด ์‚ฌ์šฉ์ž ์ž…๋ ฅ์—์„œ ๋ฐ์ดํ„ฐ ๊ณต๋ฐฑ ์ œ๊ฑฐ
โœ” .preventํ™œ์šฉํ•ด form์˜ ๊ธฐ๋ณธ ์ด๋ฒคํŠธ ๋™์ž‘ ๋ง‰๊ธฐ

  1. views/CreateView.vue ์ฝ”๋“œ ํ™•์ธ
<script>
export default {
  name: 'CreateView',
  data() {
    },
  methods: {
    createArticle() {
      const title = this.title
      const content = this.content
      if (!title) {
        alert('์ œ๋ชฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”')
        return
      } else if (!content) {
        alert('๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”')
        return
      }
    }
  }
}
</script>

โœ” title, content๊ฐ€ ๋น„์—ˆ๋‹ค๋ฉด alert๋ฅผ ํ†ตํ•ด ๊ฒฝ๊ณ ์ฐฝ์„ ๋„์šฐ๊ณ  AJAX ์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š๋„๋ก return ์‹œ์ผœ ํ•จ์ˆ˜๋ฅผ ์ข…๋ฃŒ

  1. views/CreateView.vue ์ฝ”๋“œ ํ™•์ธ
// views/CreateView.vue

<script>
import axios from 'axios'

const API_URL = 'http://127.0.0.1:8000'

export default {
  name: 'CreateView',
  methods: {
    createArticle() {
      const title = this.title
      const content = this.content
      if (!title) {
        alert('์ œ๋ชฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”')
        return
      } else if (!content) {
        alert('๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”')
        return
      }
      axios({
        method: 'post',
        url: `${API_URL}/api/v1/articles/`,
        data: {
          title: title,
          content: content
        }
      })
        .then((res) => {
          console.log(res)
        })
        .catch((err) => {
          console.log(err)
        })
    }
  }
}
</script>

โœ” axios๋ฅผ ์‚ฌ์šฉํ•ด server์— ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ฑ ์š”์ฒญ
โœ” state๋ฅผ ๋ณ€ํ™” ์‹œํ‚ค๋Š” ๊ฒƒ์ด ์•„๋‹Œ DB์— ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ฑ ํ›„ ArticleView๋กœ ์ด๋™ํ•  ๊ฒƒ์ด๋ฏ€๋กœ methods์—์„œ ์ง์ ‘ ์ฒ˜๋ฆฌ

  1. router/index.js
// router/index.js

import CreateView from '@/views/CreateView'



Vue.use(VueRouter)

const routes = [
  ...

  {
    path: '/create',
    name: 'CreateView',
    component: CreateView
  },
  ...
]
  1. views/ArticleView.vue
<template>
  <div>
    <h1>Article Page</h1>
    <router-link :to="{ name: 'CreateView' }">[CREATE]</router-link>
    <hr>
    <ArticleList/>
  </div>
</template>

โœ” router-link๋ฅผ ํ†ตํ•ด CreateView๋กœ ์ด๋™

  1. views/CreateView.vue
// views/CreateView.vue

<script>
import axios from 'axios'

const API_URL = 'http://127.0.0.1:8000'

export default {
  name: 'CreateView',
  methods: {
    createArticle() {
      const title = this.title
      const content = this.content
      if (!title) {
        alert('์ œ๋ชฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”')
        return
      } else if (!content) {
        alert('๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”')
        return
      }
      axios({
        method: 'post',
        url: `${API_URL}/api/v1/articles/`,
        data: {
          title: title,
          content: content
        }
      })
        .then(() => {
          this.$router.push({name: 'ArticleView'})
        })
        .catch((err) => {
          console.log(err)
        })
    }
  }
}
</script>

โœ” ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ฑ ์™„๋ฃŒ ํ›„ ArticleView๋กœ ์ด๋™
โœ” ์‘๋‹ต ํ™•์ธ์„ ์œ„ํ•ด ์ •์˜ํ•œ ์ธ์ž res์ œ๊ฑฐ

  1. ๊ฒฐ๊ณผ ํ™•์ธ

โœ” ArticleView๊ฐ€ create๋  ๋•Œ๋งˆ๋‹ค server์— ๊ฒŒ์‹œ๊ธ€ ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ธฐ ๋•Œ๋ฌธ์— router๋งŒ ์ด๋™ํ•ด๋„ ๋ณด์ธ๋‹ค.

[์ฐธ๊ณ ] ์ง€๊ธˆ ์š”์ฒญ ๋ฐฉ์‹์ด ๊ณผ์—ฐ ํšจ์œจ์ ์ธ๊ฐ€?

โœ” ์ „์ฒด ๊ฒŒ์‹œ๊ธ€ ์ •๋ณด๋ฅผ ์š”์ณฅํ•ด์•ผ ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ๊ฒŒ์‹œ๊ธ€์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
โœ” vuex state๋ฅผ ํ†ตํ•ด ์ „์ฒด ๊ฒŒ์‹œ๊ธ€ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๋„๋ก ๊ตฌ์„ฑํ•œ๋‹ค๋ฉด...?
โœ” ๋‚˜ ์ด์™ธ ์œ ์ €๋“ค์ด ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑํ•œ ๊ฒŒ์‹œ๊ธ€์€ ์–ธ์ œ ๋ถˆ๋Ÿฌ์™€์•ผ ํ•˜๋Š”๊ฐ€...?

Article Detail

  1. views/DetailView.vue

<template>
  <div>
    <h1>Detail</h1>
    <!-- <p>๊ธ€ ๋ฒˆํ˜ธ : {{ article?.id }}</p>
    <p>์ œ๋ชฉ : {{ article?.title }}</p>
    <p>๋‚ด์šฉ : {{ article?.content }}</p>
    <p>์ž‘์„ฑ์‹œ๊ฐ„ : {{ article?.created_at }}</p>
    <p>์ˆ˜์ •์‹œ๊ฐ„ : {{ article?.updated_at }}</p> -->
  </div>
</template>

<script>
export default {
  name: 'DetailView',
  data() {
  },
  created() {
  },
  methods: {
  }
}
</script>

โœ” ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ ์ •๋ณด๋ฅผ ํ‘œํ˜„ํ•  ์ปดํฌ๋„ŒํŠธ
โœ” AJAX ์š”์ฒญ์œผ๋กœ ์‘๋‹ต ๋ฐ›์•„์˜ฌ article์˜ ์ƒ์„ธ ์ •๋ณด๋“ค์„ ํ‘œํ˜„

  1. router/index.js ๋“ฑ๋ก
// router/index.js

..
import DetailView from '@/views/DetailView'
...

Vue.use(VueRouter)

const routes = [
  ...
  {
    path: '/:id',
    name: 'DetailView',
    component: DetailView,
  },
]

โœ” id๋ฅผ ๋™์ ์ธ์ž๋กœ ๋ฐ›์•„ ํŠน์ • ๊ฒŒ์‹œ๊ธ€์— ๋Œ€ํ•œ ์š”์ฒญ

  1. components/ArticleListItem.vue
// compoents/ArticleListItem.vue

<template>
  <div>
    <h5>{{ article.id }}</h5>
    <p>{{ article.title }}</p>
    <router-link
      :to="{
        name: 'DetailView',
        params: { id: article.id }
      }"
    >
      [DETAIL]
    </router-link>
    <hr>
  </div>
</template>

<script>
export default {
  name: 'ArticleListItem',
  props: {
    article: Object
  }
}
</script>

โœ” router-link๋ฅผ ํ†ตํ•ด ํŠน์ • ๊ฒŒ์‹œ๊ธ€์˜ id๊ฐ’์„ ๋™์  ์ธ์ž๋กœ ์ „๋‹ฌ
โœ” ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ ์ •๋ณด๋ฅผ server์— ์š”์ฒญ

  1. views/DetailView.vue
// views/DetailView.vue

<script>
import axios from 'axios'

const API_URL = 'http://127.0.0.1:8000'

export default {
  name: 'DetailView',
  created() {
    this.getArticleDetail()
  },
  methods: {
    getArticleDetail() {
      axios({
        method: 'get',
        url: `${API_URL}/api/v1/articles/${this.$route.params.id}/`
      })
        .then((res) => {
          console.log(res)
        })
        .catch((err) => {
          console.log(err)
        })
    }
  }
}
</script>

โœ” this.$route.params๋ฅผ ํ™œ์šฉํ•ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ create๋  ๋•Œ ๋„˜๊ฒจ๋ฐ›์€ id๋กœ ์ƒ์„ธ ์ •๋ณด AJAX ์š”์ฒญ

  1. ์š”์ฒญ ๊ฒฐ๊ณผ ํ™•์ธ
  1. views/DetailView.vue ์ˆ˜์ •
// views/DetailView.vue

<template>
  <div>
    <h1>Detail</h1>
    <p>๊ธ€ ๋ฒˆํ˜ธ : {{ article?.id }}</p>
    <p>์ œ๋ชฉ : {{ article?.title }}</p>
    <p>๋‚ด์šฉ : {{ article?.content }}</p>
    <p>์ž‘์„ฑ์‹œ๊ฐ„ : {{ article?.created_at }}</p>
    <p>์ˆ˜์ •์‹œ๊ฐ„ : {{ article?.updated_at }}</p>
  </div>
</template>

<script>
import axios from 'axios'

const API_URL = 'http://127.0.0.1:8000'

export default {
  name: 'DetailView',
  data() {
    return {
      article:null
    }
  },
  created() {
    this.getArticleDetail()
  },
  methods: {
    getArticleDetail() {
      axios({
        method: 'get',
        url: `${API_URL}/api/v1/articles/${this.$route.params.id}/`
      })
        .then((res) => {
          this.article=res.data
        })
        .catch((err) => {
          console.log(err)
        })
    }
  }
}
</script>

โœ” ์‘๋‹ต ๋ฐ›์€ ์ •๋ณด๋ฅผ data์— ์ €์žฅ
โœ” data์— ๋‹ด๊ธฐ๊นŒ์ง€ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋ฏ€๋กœ optional chaining์„ ํ™œ์šฉํ•ด ๋ฐ์ดํ„ฐ ํ‘œ๊ธฐ

  1. ๊ฒฐ๊ณผ ํ™•์ธ

'โญ Personal_Study > Vue' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

DRF Auth with Vue  (0) 2022.11.23
DFR Auth System  (0) 2022.11.22
Cross - Origin Resource Sharing (CORS)  (0) 2022.11.20
Vue with DRF: Server & Client  (0) 2022.11.20
Article with Vue  (0) 2022.11.19

๋Œ“๊ธ€