// views/SignUpView.vue
<template>
<div>
<h1>Sign Up Page</h1>
<form @submit.prevent="signUp">
<label for="username">username : </label>
<input type="text" id="username" v-model="username"><br>
<label for="password1"> password : </label>
<input type="password" id="password1" v-model="password1"><br>
<label for="password2"> password confirmation : </label>
<input type="password" id="password2" v-model="password2">
<input type="submit" value="SignUp">
</form>
</div>
</template>
// router/index.js
...
import SignUpView from '@/views/SignUpView'
...
Vue.use(VueRouter)
const routes = [
...
{
path: '/signup',
name: 'SignUpView',
component: SignUpView
},
]
// src/App.vue
<template>
<div id="app">
<nav>
<router-link :to="{ name: 'ArticleView' }">Articles</router-link> |
<router-link :to="{ name: 'SignUpView' }">SignUpPage</router-link>
</nav>
<router-view/>
</div>
</template>
views/SignUpView.vue
결과 확인// views/SignUpView.vue
<script>
export default {
name: 'SignUpView',
data() {
username: null,
password1: null,
password2: null,
},
methods: {
signUp() {
const username = this.username
const password1 = this.password1
const password2 = this.password2
const payload = {
username, password1, password2
}
this.$store.dispatch('signUp', payload)
}
}
}
</script>
// store/index.js
actions: {
signUp(context, payload) {
const username = payload.username
const password1 = payload.password1
const password2 = payload.password2
axios({
method: 'post',
url: `${API_URL}/accounts/signup/`,
data: {
username, password1, password2
}
})
.then(res => {
context.commit('SIGN_UP', res.data.key)
})
.catch(err => console.log(err))
},
// store/index.js
export default new Vuex.Store({
state: {
token: null,
},
getters: {
},
mutations: {
//auth
SIGN_UP(state, token) {
state.token = token
},
},
$ npm install vuex-persistedstate
// store/index.js
import createPersistedState from 'vuex-persistedstate'
export default new Vuex.Store({
plugins: [
createPersistedState(),
],
...
// views/LogInView.vue
<template>
<div>
<h1>LogIn Page</h1>
<form @submit.prevent="login">
<label for="username">username : </label>
<input type="text" id="username" v-model="username"><br>
<label for="password"> password : </label>
<input type="password" id="password" v-model="password"><br>
<input type="submit" value="logIn">
</form>
</div>
</template>
// router/index.js
...
import LogInView from '@/views/LogInView'
...
const routes = [
...
{
path: '/login',
name: 'LogInView',
component: LogInView
},
]
// src/App.vue
<template>
<div id="app">
<nav>
<router-link :to="{ name: 'ArticleView' }">Articles</router-link> |
<router-link :to="{ name: 'SignUpView' }">SignUpPage</router-link> |
<router-link :to="{ name: 'LogInView' }">LogInPage</router-link>
</nav>
<router-view/>
</div>
</template>
SAVE_TOKEN mutations
로 대체 가능// views/LogInView.vue
export default {
name: 'LogInView',
data() {
return {
username: null,
password: null,
}
},
methods: {
login() {
const username = this.username
const password = this.password
const payload = {
username, password
}
this.$store.dispatch('login', payload)
}
}
}
// store/index.js
actions: {
...
login(context, payload) {
const username = payload.username
const password = payload.password
axios({
method: 'post',
url: `${API_URL}/accounts/login/`,
data: {
username, password
}
})
.then((res) => {
context.commit('SAVE_TOKEN', res.data.key)
})
.catch((err) => {
console.log(err)
})
}
}
SAVE_TOKEN
호출 확인// store/index.js
mutations: {
...
//auth
// SIGN_UP(state, token) {
// state.token = token
// },
SAVE_TOKEN(state, token) {
state.token = token
}
},
actions: {
...
signUp(context, payload) {
const username = payload.username
const password1 = payload.password1
const password2 = payload.password2
axios({
method: 'post',
url: `${API_URL}/accounts/signup/`,
data: {
username, password1, password2
}
})
.then(res => {
console.log(res)
context.commit('SAVE_TOKEN', res.data.key)
})
.catch(err => console.log(err))
},
...
// store/index.js
export default new Vuex.Store({
...
getters: {
isLogin(state) {
return state.token ? true : false
}
},
})
// views/ArticleView.vue
export default {
name: 'ArticleView',
components: {
ArticleList,
},
computed:{
isLogin() {
return this.$store.getters.isLogin // 로그인 여부
}
},
created() {
this.getArticles()
},
methods: {
getArticles() {
// 로그인이 되어 있으면 getArticles action 실행하고
if (this.isLogin) {
this.$store.dispatch('getArticles')
}
// 로그인 되어 있지 않으면 login 페이지로 이동
else {
alert('로그인이 필요한 서비스 입니다.')
this.$router.push({ name: 'LogInView' })
}
}
}
}
// store/index.js
import router from '../router'
export default new Vuex.Store({
...
mutations: {
//auth
SIGN_UP(state, token) {
state.token = token
router.push({ name: 'ArticleView' })
},
},
💡 이제 인증 여부를 확인하기 위한 Token 이 준비되었으니, headers HTTP에 Token을 담아 요청을 보내면 된다!
getArticles()
headers에 Authorizations 와 token 추가// store/index.js
actions: {
getArticles(context) {
axios({
method: 'get',
url: `${API_URL}/api/v1/articles/`,
headers: {
Authorization: `Token ${ context.state.token }`
}
})
.then((res) => {
// console.log(res, context)
context.commit('GET_ARTICLES', res.data)
})
.catch((err) => {
console.log(err)
})
},
createArticle()
headers에 Authorization 와 token 추가// views/CreateView.vue
export default {
...
methods: {
createArticle() {
...
axios({
method: 'post',
url: `${API_URL}/api/v1/articles/`,
data: { title, content},
headers: {
Authorization: `Token ${ this.$store.state.token }`
},
})
.then(() => {
// console.log(res)
this.$router.push({name: 'ArticleView'})
})
.catch((err) => {
console.log(err)
})
}
}
}
# articles/models.py
from django.db import models
from django.conf import settings
# Create your models here.
class Article(models.Model):
# User정보를 Vue에서도 확인 가능하도록 정보 제공
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)
makemigrations
& migrate
username field
정의 필요comment_count
field 정의 방법 참고# articles/serializers.py
class ArticleListSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username', read_only=True)
class Meta:
model = Article
fields = ('id', 'title', 'content', 'user', 'username')
class ArticleSerializer(serializers.ModelSerializer):
comment_set = CommentSerializer(many=True, read_only=True)
comment_count = serializers.IntegerField(source='comment_set.count', read_only=True)
username = serializers.CharField(source='user.username', read_only=True)
class Meta:
model = Article
fields = '__all__'
read_only_fields = ('user', )
# articles/views.py
@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def article_list(request):
if request.method == 'GET':
# articles = Article.objects.all()
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
# serializer.save()
serializer.save(user=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
// components/ArticleListItem.vue
<template>
<div>
<h5>{{ article.id }}</h5>
<p>{{ article.title }}</p>
<p>작성자 : {{ article.username }}</p>
<router-link :to="{
name: 'DetailView',
params: {id: article.id }}">
[DETAIL]
</router-link>
<hr>
</div>
</template>
https://github.com/mjieun0956/TIL/tree/master/Vue/14.%20DRF%20Auth%20with%20Vue/front-server
고수