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

Vue with DRF: Server & Client

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

Vue with DRF

Server & Client

Server

โœ” ํด๋ผ์ด์–ธํŠธ์— ์ •๋ณด์™€ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ปดํ“จํ„ฐ ์‹œ์Šคํ…œ
โœ” ์„œ๋น„์Šค ์ „์ฒด๋ฅผ ์ œ๊ณต -> Django Web Service
โœ” ์ •๋ณด๋ฅผ ์ œ๊ณต -> Django API Service


โœ” DB์™€ ํ†ต์‹ ํ•˜๋ฉฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑ, ์กฐํšŒ, ์ˆ˜์ •, ์‚ญ์ œ๋ฅผ ๋‹ด๋‹น

Client

โœ” Server๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์„œ๋น„์Šค์— ์ ์ ˆํ•œ ์š”์ฒญ์„ ํ†ตํ•ด Server๋กœ๋ถ€ํ„ฐ ๋ฐ˜ํ™˜ ๋ฐ›์€ ์‘๋‹ต์„ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ‘œํ˜„ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํ”„๋กœ๊ทธ๋žจ ํ˜น์€ ์‹œ์Šคํ…œ


โœ” ์‘๋‹ต๋ฐ›์€ ์ •๋ณด๋ฅผ ๊ฐ€๊ณตํ•˜์—ฌ ํ™”๋ฉด์— ํ‘œํ˜„

DRF

Back skeleton ์ฝ”๋“œ ํ™•์ธ

  1. Models
from django.db import models
from django.conf import settings

# Create your models here.
class Article(models.Model):
    # user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


class Comment(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

  1. ์š”์ฒญ ๊ฒฝ๋กœ ํ™•์ธ
# articles/urls.py

# from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
from django.urls import path
from . import views


urlpatterns = [
    path('articles/', views.article_list),
    path('articles/<int:article_pk>/', views.article_detail),
    path('comments/', views.comment_list),
    path('comments/<int:comment_pk>/', views.comment_detail),
    path('articles/<int:article_pk>/comments/', views.comment_create),
    # # ํ•„์ˆ˜ ์ž‘์„ฑ
    # path('schema/', SpectacularAPIView.as_view(), name='schema'),
    # # optional UI
    # path('swagger/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
]
# my_api/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include('articles.urls')),
    # path('accounts/', include('dj_rest_auth.urls')),
    # path('accounts/signup/', include('dj_rest_auth.registration.urls'))
]
  1. ๋”๋ฏธ ๋ฐ์ดํ„ฐ ์‚ฝ์ž…

Vue

front ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ ํ™•์ธ

๋ฉ”์ธ ํŽ˜์ด์ง€ ๊ตฌ์„ฑ

  1. views/ArticleView.vue component ํ™•์ธ ๋ฐ route ๋“ฑ๋ก
// src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import ArticleView from '@/views/ArticleView'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'ArticleView',
    component: ArticleView
  },
  ...
]
// src/views/ArticleView.vue

<template>
  <div>
    <h1>Article Page</h1>
    <hr />
  </div>
</template>

<script>
export default {
  name: "ArticleView",
  components: {},
  computed: {},
  created() {},
  methods: {},
};
</script>
  1. src/App.vue router-link ๋“ฑ๋ก
// src/App.vue

<nav>
  <router-link :to="{ name: 'ArticleView' }">Articles</router-link>
</nav>
  1. components/ArticleList.vue ํ™•์ธ
// components/ArticleList.vue

<template>
  <div class="article-list">
    <h3>Article List</h3>
  </div>
</template>

<script>

export default {
  name: 'ArticleList',
  components: {
  },
  computed: {
  }
}
</script>

<style>
.article-list {
  text-align: start;
}
</style>
  1. ArticleList ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ ๋“ฑ๋ก
// views/ArticleView.vue

<template>
  <div>
    <h1>Article Page</h1>
    <hr>
    <ArticleList/>
  </div>
</template>

<script>
import ArticleList from '@/components/ArticleList'


export default {
  name: 'ArticleView',
  components: {
    ArticleList
  },
  computed:{
  },
  created() {
  },
  methods: {
  }
}
</script>
  1. components/ArticleListItem.vue ํ™•์ธ
// compoents/ArticleListItem.vue

<template>
  <div>
    <h5>PK</h5>
    <p>์ œ๋ชฉ</p>
    <hr>
  </div>
</template>

<script>
export default {
  name: 'ArticleListItem',
}
</script>
  1. ArticleListItem ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ ๋“ฑ๋ก
// components/ArticleList.vue

<template>
  <div class="article-list">
    <h3>Article List</h3>
    <ArticleListItem/>
  </div>
</template>

<script>
import ArticleListItem from '@/components/ArticleListItem'

export default {
  name: 'ArticleList',
  components: {
    ArticleListItem
  },
  computed: {
  }
}
</script>
  1. store/index.js state์— article ๋ฐฐ์—ด ์ •์˜
// store/index.js


export default new Vuex.Store({
  state: {
    articles: [
      {
        id: 1,
        title: '์ œ๋ชฉ',
        content: '๋‚ด์šฉ'
      },
      {
        id: 2,
        title: '์ œ๋ชฉ2',
        content: '๋‚ด์šฉ2'
      },
    ],
  },
})
  1. state์—์„œ articles ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์™€์„œ pass props
// components/ArticleList.vue

<template>
  <div class="article-list">
    <h3>Article List</h3>
    <ArticleListItem
      v-for="article in articles"
      :key="article.id"
      :article='article'
    />
  </div>
</template>

<script>
import ArticleListItem from '@/components/ArticleListItem'

export default {
  name: 'ArticleList',
  components: {
    ArticleListItem
  },
  computed: {
    articles() {
      return this.$store.state.articles
    }
  }
}
</script>
  1. ๋‚ด๋ ค ๋ฐ›์€ prop ๋ฐ์ดํ„ฐ๋กœ ํ™”๋ฉด ๊ตฌ์„ฑ
// compoents/ArticleListItem.vue

<template>
  <div>
    <h5>{{ article.id }}</h5>
    <p>{{ article.title }}</p>
    <hr>
  </div>
</template>

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

Vue with DRF

AJAX ์š”์ฒญ ์ค€๋น„

  1. axios ์„ค์ •
$ npm install axios
// store/index.js

import axios from 'axios'

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

โœ” ์š”์ฒญ ๋ณด๋‚ผ API server ๋„๋ฉ”์ธ ๋ณ€์ˆ˜์— ๋‹ด๊ธฐ

  1. getArticles ๋ฉ”์„œ๋“œ ์ •์˜
// store/index.js

export default new Vuex.Store({
  ...
  actions: {
    getArticles(context) {
      axios({
        method: 'get',
        url: `${API_URL}/api/v1/articles/`
      })
        .then((res) => {
          console.log(res, context)
        })
        .catch((err) => {
          console.log(err)
        })
    }
  },
})
  1. view์—์„œ getArticles actions ํ˜ธ์ถœ
// vies/ArticleView.vue

<script>
import ArticleList from '@/components/ArticleList'


export default {
  name: 'ArticleView',
  components: {
    ArticleList
  },
  computed:{
  },
  created() {
    this.getArticles()
  },
  methods: {
    getArticles() {
      this.$store.dispatch('getArticles')
    }
  }
}
</script>

โœ” ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋œ ์งํ›„ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด created() hook ์‚ฌ์šฉ

์š”์ฒญ ๊ฒฐ๊ณผ ํ™•์ธ

โœ” server์—์„œ๋Š” 200์„ ๋ฐ˜ํ™˜ํ•˜์˜€์œผ๋‚˜ client console์—์„œ๋Š” Error ๋ฐœ์ƒ!

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

Vue with DRF  (0) 2022.11.21
Cross - Origin Resource Sharing (CORS)  (0) 2022.11.20
Article with Vue  (0) 2022.11.19
Navigation Guard  (0) 2022.11.19
Vue Router  (0) 2022.11.18

๋Œ“๊ธ€