Django + Ajax에서 좋아하는 버튼 구현

1. 소개



기념해야 할 Qiita 첫 포스트입니다.

Twitter를 사랑하는 사람이지만 업무 중에 Twitter는 만지지 않는다. 그래서 생각이나 메모를 쓰는 트위터 스타일 앱을 만들기 시작했는데, 좋아요 버튼의 구현이 꽤 어렵습니다. . .
form로 하면 페이지의 천이를 수반해, Twitter감이 얇아져 버리기 때문에 다른 방법을 모색.
그럴 때, Ajax라는 것을 알고 어떻게든 구현할 수 있었기 때문에 투고해 보려고 생각한 대로입니다.



Web프레임워크나 DB에 대해서 공부하기 시작했을 뿐이므로, 실수등 있으면 교수 받을 수 있으면 다행입니다.

2. 구현 & 해설



이번에는 form에서 입력한 데이터를 DB에 저장하는 부분의 설명은 생략하므로 미리 양해 바랍니다.

urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.timeline, name='index'),
    path('like/', views.like, name='like'),
]

라우팅 설정. httpresponse를 반환하는 페이지를 설정합니다.

models.py
from django.db import models
from django.utils import timezone

class PostTweet(models.Model):
    memo = models.TextField(max_length=140)
    published = models.DateTimeField(default=timezone.now)
    star = models.BooleanField(default=False)

models.py에서는 메모 내용 외에도 "좋아요"상태를 나타내는 부울 값을 정의합니다.

forms.py
class PostForm(forms.ModelForm):
    class Meta:
        model = PostTweet
        fields = ['memo', 'published', 'star']

forms.py는 이런 느낌. 특필하지는 않지만 일단 적재합니다.

views.py
from django.http import HttpResponse
from django.shortcuts import render
from .models import PostTweet
from .forms import PostForm, SearchForm

def index(request):
    posts = PostTweet.objects.all().order_by('-published')
    form = PostForm()
    d = {
        'form': form,
        'posts': posts
    }
    return render(request, 'index.html', d)

def like(request):
    if request.method == 'GET':
        if 'star' in request.GET:
            like = PostTweet.objects.get(id=int(request.GET['star']))
            like.star = not like.star
            like.save()
            return HttpResponse('OK')
    else:
        return HttpResponse("NG")

like()에 대해서는 나중에 설명합니다.

index.html
{% extends 'base.html' %}
{% block body %}
    {% for post in posts %}
        {{ post.memo | linebreaker }}
        <br>
        {% if post.star == False %}
            <input type="checkbox" class="like" id="like_{{ post.id }}" 
                   data_id="{{ post.id }}">
        {% else %}
            <input type="checkbox" class="like" checked="checked" id="like_{{ post.id }}"
                   data_id="{{ post.id }}">
        {% endif %}
        <label for="like_{{ post.id }}" class="like_label"></label>

    <script src="https://code.jquery.com/jquery-3.5.0.js" 
            integrity="sha256-r/AaFHrszJtwpe+tHyNi/XCfMxYpbsRg2Uqn0x3s2zc=" 
            crossorigin="anonymous"></script>
    <script type="text/javascript">
        $('.like').click(function(){
            var id;
            id = $(this).attr("data_id");
            $.ajax(
                {
                    type:"GET",
                    url: "like",
                    data:{
                        star: id
                        }
                })
            });
    </script>
{% endblock %}

확인란과 라벨을 사용하여 좋아요 버튼을 표현하기로 결정했습니다.
좋아하는 상태를 나타내는 star이 True이면 체크 박스를 미리 checked로 둡니다.

base.html에 대해서는 생략.

style.css
.like{
    display: none;
}
.like_label{
    margin-left: 10px;
    cursor: pointer;
    color: #cccccc;
    border: none;  /* 枠線を消す */
    outline: none; /* クリックしたときに表示される枠線を消す */
    background: transparent; /* 背景の灰色を消す */
}
input:checked + .like_label{
    color: gold;
}

외형 업데이트



버튼 표시를 지우고 레이블만 표시하도록 합니다.
기본 버튼 레이블의 색상은 회색입니다.
체크박스가 체크되어 있으면 버튼 라벨의 색상을 gold로 변경합니다.

이렇게 하면 버튼을 누를 때마다 색상이 바뀝니다.

DB 업데이트



jQuery를 가져옵니다.
Ajax (javascript 비동기 처리)를 사용하여 누른 버튼의 레코드 id를 views.py의 like 메소드에 반환합니다. (id는 DB에 추가하면 자동으로 추가됩니다.)
그리고 views.py의 like()에서 얻은 id의 star를 not star로 업데이트합니다.

이렇게하면 버튼을 누를 때마다 DB의 내용이 업데이트됩니다.

요약



Ajax와 체크 박스를 사용하여 좋은 느낌의 좋아요 버튼을 구현할 수있었습니다.
이번 앱은 자신 밖에 보지 않는 전제이므로 온 오프 밖에 없습니다만, 좋아하는 수를 카운트하는 타입도 똑같이 만들 수 있는 것은 아닐까요.

여기까지 읽어 주셔서 감사합니다!

좋은 웹페이지 즐겨찾기