좋아요 새로고침없이하기!
가상환경만들기
python -m venv venv
activate
python manage.py migrate
python manage.py seed articcles --number=30
python manage.py runserver
브라우저에서 like 을 누르면 json으로 django로 이동하게?
articles > templates > index
https://github.com/axios/axios
CND 활성화 스크립터 넣어주기
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
https://developer.mozilla.org/ko/docs/Web/API/HTMLOrForeignElement/dataset
에서 script 에서 pk 넣는 방식? 을 확인할수있다
<form class="like-form" id="article-{{ article.pk }}">
index.html
{% extends 'base.html' %}
{% block content %}
<h1>Articles</h1>
{% if request.user.is_authenticated %}
<a href="{% url 'articles:create' %}">[CREATE]</a>
{% else %}
<a href="{% url 'accounts:login' %}">[새 글을 작성하려면 로그인하세요.]</a>
{% endif %}
<hr>
{% for article in articles %}
<p>
<b>작성자 : <a href="{% url 'accounts:profile' article.user.username %}">{{ article.user }}</a></b>
</p>
<p>글 번호 : {{ article.pk }}</p>
<p>글 제목 : {{ article.title }}</p>
<p>글 내용 : {{ article.content }}</p>
<div>
<form class="like-form" data-article-id="{{ article.pk }}">
{% csrf_token %}
{% if request.user in article.like_users.all %}
<button id="like-{{ article.pk }}">좋아요 취소</button>
{% else %}
<button id="like-{{ article.pk }}">좋아요</button>
{% endif %}
</form>
</div>
<p>
<span id="like-count-{{ article.pk }}">{{ article.like_users.all|length }}</span>명이 이 글을 좋아합니다.
</p>
<a href="{% url 'articles:detail' article.pk %}">[DETAIL]</a>
<hr>
{% endfor %}
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
const forms = document.querySelectorAll('.like-form')
forms.forEach((form) => {
form.addEventListener('submit', function(event) {
event.preventDefault() //동작 취소
//console.log(form.dataset)
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value
const articleId = form.dataset.articleId
// pk가져오는 방법 ????에는 pk가 들어가야한다.
const requestUrl = `http://127.0.0.1:8000/articles/${articleId}/likes/`
//console.log('test test!')// 잘 눌려지는지 확인
const config = {
headers: {'X-CSRFToken': csrftoken},
}
axios.post(requestUrl, {}, config)
.then((res) => {
//console.log(res)
//console.log(res.data)
const liked = res.data.liked
const likeBtn = document.querySelector(`#like-${articleId}`)
const likeCount = document.querySelector(`#like-count-${articleId}`)
likeBtn.innerText = liked? '좋아요 취소' : '좋아요'
// 위와 아래는 상동합니다.
//if (liked) {
// likeBtn.innerTest = '좋아요 취소'
//}else {
// likeBtn.innerTest = '좋아요'
//}
likeCount.innerText = res.data.like_count
})
.catch((err) => {
console.error(err)
})
})
})
</script>
{% endblock %}
views.py
@require_POST
def likes(request, article_pk):
if request.user.is_authenticated:
article = get_object_or_404(Article, pk=article_pk)
if article.like_users.filter(pk=request.user.pk).exists():
# if request.user in article.like_users.all():
# 좋아요 취소
article.like_users.remove(request.user)
liked = False
else:
# 좋아요 누름
article.like_users.add(request.user)
liked = True
data = {
#'test': '잘 넘어가나요?',
'liked':liked,
'like_count':article.like_users.count(),
}
#더이상 html이아닌 json을 받을것이다
return JsonResponse(data)
return redirect('accounts:login')
아이콘만들기
https://fontawesome.com/icons?d=gallery&p=2&q=heart
https://icons.getbootstrap.com/
아이콘 사이트 둘중 아무거나사용
저는 부트스트랩 아이콘(아래링크)로가서
엄지척 아이콘을 선택했습니다.
안에 색있는거
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hand-thumbs-up-fill" viewBox="0 0 16 16">
<path d="M6.956 1.745C7.021.81 7.908.087 8.864.325l.261.066c.463.116.874.456 1.012.965.22.816.533 2.511.062 4.51a9.84 9.84 0 0 1 .443-.051c.713-.065 1.669-.072 2.516.21.518.173.994.681 1.2 1.273.184.532.16 1.162-.234 1.733.058.119.103.242.138.363.077.27.113.567.113.856 0 .289-.036.586-.113.856-.039.135-.09.273-.16.404.169.387.107.819-.003 1.148a3.163 3.163 0 0 1-.488.901c.054.152.076.312.076.465 0 .305-.089.625-.253.912C13.1 15.522 12.437 16 11.5 16H8c-.605 0-1.07-.081-1.466-.218a4.82 4.82 0 0 1-.97-.484l-.048-.03c-.504-.307-.999-.609-2.068-.722C2.682 14.464 2 13.846 2 13V9c0-.85.685-1.432 1.357-1.615.849-.232 1.574-.787 2.132-1.41.56-.627.914-1.28 1.039-1.639.199-.575.356-1.539.428-2.59z"/>
</svg>
없는거
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hand-thumbs-up" viewBox="0 0 16 16"> <path d="M8.864.046C7.908-.193 7.02.53 6.956 1.466c-.072 1.051-.23 2.016-.428 2.59-.125.36-.479 1.013-1.04 1.639-.557.623-1.282 1.178-2.131 1.41C2.685 7.288 2 7.87 2 8.72v4.001c0 .845.682 1.464 1.448 1.545 1.07.114 1.564.415 2.068.723l.048.03c.272.165.578.348.97.484.397.136.861.217 1.466.217h3.5c.937 0 1.599-.477 1.934-1.064a1.86 1.86 0 0 0 .254-.912c0-.152-.023-.312-.077-.464.201-.263.38-.578.488-.901.11-.33.172-.762.004-1.149.069-.13.12-.269.159-.403.077-.27.113-.568.113-.857 0-.288-.036-.585-.113-.856a2.144 2.144 0 0 0-.138-.362 1.9 1.9 0 0 0 .234-1.734c-.206-.592-.682-1.1-1.2-1.272-.847-.282-1.803-.276-2.516-.211a9.84 9.84 0 0 0-.443.05 9.365 9.365 0 0 0-.062-4.509A1.38 1.38 0 0 0 9.125.111L8.864.046zM11.5 14.721H8c-.51 0-.863-.069-1.14-.164-.281-.097-.506-.228-.776-.393l-.04-.024c-.555-.339-1.198-.731-2.49-.868-.333-.036-.554-.29-.554-.55V8.72c0-.254.226-.543.62-.65 1.095-.3 1.977-.996 2.614-1.708.635-.71 1.064-1.475 1.238-1.978.243-.7.407-1.768.482-2.85.025-.362.36-.594.667-.518l.262.066c.16.04.258.143.288.255a8.34 8.34 0 0 1-.145 4.725.5.5 0 0 0 .595.644l.003-.001.014-.003.058-.014a8.908 8.908 0 0 1 1.036-.157c.663-.06 1.457-.054 2.11.164.175.058.45.3.57.65.107.308.087.67-.266 1.022l-.353.353.353.354c.043.043.105.141.154.315.048.167.075.37.075.581 0 .212-.027.414-.075.582-.05.174-.111.272-.154.315l-.353.353.353.354c.047.047.109.177.005.488a2.224 2.224 0 0 1-.505.805l-.353.353.353.354c.006.005.041.05.041.17a.866.866 0 0 1-.121.416c-.165.288-.503.56-1.066.56z"/> </svg>
위코드 넣어주기
팔로우도해봅시다!
views.py 함수
form tag 변경해주기
id로하는 이유는 버튼이 유일하기때문에!
여러개면 class 가 편합니당
<form id=
script 적어주기
<script> const form = document.querySelector('#follow') form.addEventListener('submit', function(e) { e.preventDefault() }</script>
url 이 무엇인지봐야한다
path('<int:user_pk>/follow/', views.follow, name='follow'),
form 수정
<form id="follow" data-user-id="{{ person.id }}"
다시 form 으로 옮겨서
<script> const form = document.querySelector('#follow') form.addEventListener('submit', function(e) { e.preventDefault() console.log(form.dataset) // data-* }</script>
서버로가서 개발자도그를통해 log 를 확인해보고
<script> const form = document.querySelector('#follow') form.addEventListener('submit', function(e) { e.preventDefault() console.log(form.dataset.userId) // data-* }</script>
<script> const form = document.querySelector('#follow') form.addEventListener('submit', function(e) { e.preventDefault() form.dataset.userId // data-* const userId = e.target.dataset.userId const requestUrl = `/accounts/&{userId}/follow/` axios.post(requestUrl) }</script>
기억이안나면 console log 로 보내서 확인해보자.
<script> const form = document.querySelector('#follow') form.addEventListener('submit', function(e) { e.preventDefault() form.dataset.userId // data-* const userId = e.target.dataset.userId const requestUrl = `/accounts/&{userId}/follow/` axios.post(requestUrl) .then((response) => { console.log(response) }) .catch((err) => { console.error(err) }) }</script>
다시 돌아와서 공식문서를 참고하여 적어주자
<script> const form = document.querySelector('#follow') form.addEventListener('submit', function(e) { e.preventDefault() form.dataset.userId // data-* const userId = e.target.dataset.userId const requestUrl = `/accounts/&{userId}/follow/` const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value; const config = { headers: {'X-CSRFToken': csrftoken}, } axios.post(requestUrl, {}, config) }</script>
조금더 아름다운 방법
https://github.com/axios/axios 에서 axios API 를 보자
views.py
맨위에서
from django.http import JsonResponse
@require_POSTdef follow(request, user_pk): if request.user.is_authenticated: # 팔로우 받는 사람 you = get_object_or_404(get_user_model(), pk=user_pk) me = request.user # 나 자신은 팔로우 할 수 없다. if you != me: if you.followers.filter(pk=me.pk).exists(): # if request.user in person.followers.all(): # 팔로우 끊음 you.followers.remove(me) followed = False else: # 팔로우 신청 you.followers.add(me) followed = True data = { 'followed':followed, # 'follower_count':you.followers.count(), } return JsonResponse(data) return redirect('accounts:login')
followed 값에 따라 바꿔주면된다.
return JsonResopnse() 에서 json 으로 변환 .then에 바꿔준다.
html
<script> const form = document.querySelector('#follow') form.addEventListener('submit', function(e) { e.preventDefault() form.dataset.userId // data-* const userId = e.target.dataset.userId const requestUrl = `/accounts/&{userId}/follow/` const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value; const config = { headers: {'X-CSRFToken': csrftoken}, } axios.post(requestUrl, {}, config) }</script>
button에다가 id를 추가해줘야합니다
버튼이 1개이니까 id 주는거
<form class="follow" data-follower-id = "{{ person.pk }}"> {% csrf_token %} {% if request.user in followers %} <button id="follow-btn">언팔로우</button> {% else %} <button id="follow-btn">팔로우</button> {% endif %} </form>
<script> const form = document.querySelector('#follow') form.addEventListener('submit', function(e) { e.preventDefault() form.dataset.userId // data-* const userId = e.target.dataset.userId const requestUrl = `/accounts/&{userId}/follow/` const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value; const config = { headers: {'X-CSRFToken': csrftoken}, } axios.post(requestUrl, {}, config) .then((response) => { const followed const folloBtn- }) .catch((err) => { console.error(err) }) })</script>
views.py 로 돌아가 팔로잉/팔로워 인원수 표시
@require_POSTdef follow(request, user_pk): if request.user.is_authenticated: # 팔로우 받는 사람 you = get_object_or_404(get_user_model(), pk=user_pk) me = request.user # 나 자신은 팔로우 할 수 없다. if you != me: if you.followers.filter(pk=me.pk).exists(): # if request.user in person.followers.all(): # 팔로우 끊음 you.followers.remove(me) follow = False else: # 팔로우 신청 you.followers.add(me) follow = True data = { 'followed':followed, 'followers_count':you.followers.count(), 'followings_count':you.followings.count(), } return JsonResponse(data) return redirect('accounts:login')
html
<script>
const form = document.querySelector('#follow')
form.addEventListener('submit', function(e) {
e.preventDefault()
form.dataset.userId // data-*
const userId = e.target.dataset.userId
const requestUrl = `/accounts/&{userId}/follow/`
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
const config = {
headers: {'X-CSRFToken': csrftoken},
}
axios.post(requestUrl, {}, config)
.then((response) => {
const followed = response.data.followed
const folloBtn = document.queselector('#follow-btn')
const followersCnt = response.data.followers_count
//const followingsCnt = response.data.followings_count
//const followingsCntBox = document.querySelector('#followings-cnt')
//followingsCntBox.innerText = followingsCnt
const followersCntBox = document.querySelector('#followers-cnt')
followBtn.innerText = followed ? '팔로우 취소' : '팔로우'
followersCntBox.innerText = followersCnt
})
.catch((err) => {
console.error(err)
})
}
const form = document.querySelector('#follow')
if (form) {
form.addEventListener('submit', onFollowSubmit)
}
</script>
팔로윙 인원수 html 변경해주기
<div>
팔로잉 : <span id="followings-cnt">{{ followings|length }}</span>
/
팔로워 : <span id="followers-cnt">{{ followers|length }}</span>
</div>
html
폼이 별로다 삭제 ㄱ 버튼만 남겨둬라
{% extends 'base.html' %}
{% block content %}
<h1>{{ person.username }}님의 프로필</h1>
{% with followings=person.followings.all followers=person.followers.all %}
<div>
<div>
팔로잉 : {{ followings|length }} / 팔로워 : {{ followers|length }}
</div>
{% if request.user != person %}
<div>
{% csrf_token %}
{% if request.user in followers %}
<button id="follow-btn">언팔로우</button>
{% else %}
<button id="follow-btn">팔로우</button>
{% endif %}
</div>
{% endif %}
</div>
{% endwith %}
<hr>
<h2>{{ person.username }}'s 게시글</h2>
{% for article in person.article_set.all %}
<div>{{ article.title }}</div>
{% endfor %}
<hr>
<h2>{{ person.username }}'s 댓글</h2>
{% for comment in person.comment_set.all %}
<div>{{ comment.content }}</div>
{% endfor %}
<hr>
<h2>{{ person.username }}'s likes</h2>
{% for article in person.like_articles.all %}
<div>{{ article.title }}</div>
{% endfor %}
<hr>
<a href="{% url 'articles:index' %}">[back]</a>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
const form = document.querySelector('#follow')
form.addEventListener('submit', function(e) {
e.preventDefault()
form.dataset.userId // data-*
const userId = e.target.dataset.userId
const requestUrl = `/accounts/&{userId}/follow/`
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
const config = {
headers: {'X-CSRFToken': csrftoken},
}
axios.post(requestUrl, {}, config)
.then((response) => {
const followed = response.data.followed
const folloBtn = document.queselector('#follow-btn')
const followersCnt = response.data.followers_count
//const followingsCnt = response.data.followings_count
//const followingsCntBox = document.querySelector('#followings-cnt')
//followingsCntBox.innerText = followingsCnt
const followersCntBox = document.querySelector('#followers-cnt')
followBtn.innerText = followed ? '팔로우 취소' : '팔로우'
followersCntBox.innerText = followersCnt
})
.catch((err) => {
console.error(err)
})
}
const form = document.querySelector('#follow')
if (form) { // null check
form.addEventListener('submit', onFollowSubmit)
}
</script>
{% endblock %}
like 로그인 관련구현
views.py
from django.http import JsonResponse, HttpResponse 불러오고
@require_POST
def likes(request, article_pk):
if request.user.is_authenticated:
article = get_object_or_404(Article, pk=article_pk)
if article.like_users.filter(pk=request.user.pk).exists():
# if request.user in article.like_users.all():
# 좋아요 취소
article.like_users.remove(request.user)
liked = False
else:
# 좋아요 누름
article.like_users.add(request.user)
liked = True
data = {
#'test': '잘 넘어가나요?',
'liked':liked,
'like_count':article.like_users.count(),
}
#더이상 html이아닌 json을 받을것이다
return JsonResponse(data)
return HttpResponse(status=401)
'SSAFY > Python문법 정리' 카테고리의 다른 글
[Vue + Django] Client+ Server (0) | 2021.05.17 |
---|---|
[JS]Vue router (0) | 2021.05.10 |
[Python] Prim 알고리즘 (0) | 2021.04.21 |
[Python] 큐의 구조 (0) | 2021.03.03 |
[Python] 스택 2 (0) | 2021.02.24 |