vue.js의 template을 사용하니 document element를 직접 찾고 조작해주는 과정이 없으니 편하다. 다만 vue.js에 익숙하지 않아 vue적인 사고를 하기까지가 어렵다.
{% extends 'my_book/base.html' %}
{% load static %}
{% block style %}
<link rel="stylesheet" href="{% static 'my_book/css/navbar.css' %}">
<link rel="stylesheet" href="{% static 'my_book/css/home.css' %}">
{% endblock %}
{% block content %}
{% include 'my_book/navbar.html' %}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<main>
<article id="new-post">
<div class="title">게시물 작성</div>
<form action="" method="POST">
{% csrf_token %}
{{ form.content }}
<input class="submit-btn" type="submit" value="등록">
</form>
</article>
<section id="friend-feed">
<article :id=[[post["pk"]]] v-for="post in posts">
<div v-if="loading">로딩 중.....</div>
<div>사용자 [[ post["fields"].author ]]</div>
<span>[[ post["fields"].created_date ]]</span>
<div>[[ post["fields"].content ]]</div>
<button class="thumb" @click="thumb_up(post)"></button>
<span>좋아요 [[ post["fields"].likes ]]</span>
</article>
<div v-if="end">더 이상 불러올 게시물이 없습니다</div>
<button @click="fetch_posts()">more</button>
</section>
</main>
<script>
axios.defaults.xsrfCookieName = 'csrftoken';
axios.defaults.xsrfHeaderName = 'X-CSRFToken';
var app = new Vue({
delimiters: ['[[', ']]'],
el: '#friend-feed',
data: {
posts: [],
loading: true,
end: false,
},
methods: {
fetch_posts: function() {
if(this.end) return
this.loading = true
axios.get('../api/post-10/from/' + (this.posts.length))
.then(response => {
let data = JSON.parse(response.data)
if(data.length) {
for(var i = 0; i < data.length; i++) {
this.posts.push(data[i])
}
} else {
this.end = true
}
})
.catch(error => {
console.log(error)
})
.finally(() => {
this.loading = false
})
},
thumb_up: function(post) {
post["fields"].likes += 1
axios.post('../api/thumb-up/' + post["pk"])
},
},
mounted() {
this.fetch_posts()
}
})
</script>
{% endblock %}
기능
more 버튼을 누르면 지금까지 불러온 데이터에다 10개를 추가로 불러와서 posts 배열에 넣는다. 그러면 템플릿에서 알아서 추가적으로 DOM을 생성해준다. (물론 비동기로)
그리고 v-if 를 잘 사용하면 사용자에게 로딩 중임을 쉽게 알려줄 수 있다. 더 이상 불러올 게시물이 없는데 계속 more 버튼을 누르는 이상한 행동을 하는 사람이 있을 수도 있다. 그러한 서버 부하를 막기 위해 "더 이상 불러올 게시물이 없다"는 것을 알려주고 서버에 더 이상 get 요청을 보내지 않는다.
좋아요 버튼은 누를 경우 바로 좋아요 수를 증가시켜 브라우저에 보여주고 서버에 post 요청을 보내서 데이터베이스에 반영하도록 했다.
어려웠던 점
순수 django만 쓰다가 vue라는 자바스크립트를 다루려니까 this를 자꾸 빼먹어서 예상치 못한 결과를 낳았다. this에 주의하자. 자바스크립트에서 빈 배열은 null로 안 받는 것인가? 그래서 length로 처리했다.
django의 serializer를 사용하여 json 데이터를 템플릿으로 넘겨줬을 때 JSON.parse(response.data) 를 해주지 않으면 배열이 아닌 요상한 값이 들어가 있었다.
남은 문제
DRF를 사용하지 않고 serializer만으로 foreign key 관계의 원하는 데이터를 넘길 수 있을까? (기본적으로 foreign key 관계는 id만 전달된다.)
'django' 카테고리의 다른 글
visual stuido code 파이썬 가상환경 설정부터 startproject까지 (0) | 2021.01.31 |
---|---|
django serializer로 foreign key 관계의 원하는 값들을 가져오는 방법 (0) | 2020.12.29 |
현재 user를 필드 값으로 넣고 싶을 때 (0) | 2020.12.28 |
django에 react나 vue를 결합시켜야 하는가? (0) | 2020.12.25 |
현재 html에서 필요한 css 파일만 불러오기 (0) | 2020.12.23 |