[Django] widget (2) widget 만들어보기 - 별점 주기 rateit.js
위의 포스팅과 개별적인 내용이지만 전체적인 내용은 이어지므로 이해가 잘 가지 않는다면 위 포스팅을 참고해주시면 감사하겠습니다.
위 포스팅에서도 확인가능하듯 현재 model 은 다음과 같습니다.
# core/models.py
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
# 생략
class Student(models.Model):
university = models.ForeignKey(University, on_delete=models.CASCADE)
date_birth = models.DateField()
residencce = models.CharField(max_length=200)
photo = models.ImageField(blank=True)
grade = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)])
intro = models.TextField()
이번 포스팅에서는 여기서 학생의 성적에 해당하는 grade 를 별점을 통해 줄 수 있도록 해보겠습니다. 직접 구현할 수 도 있지만 괜찮은 모듈이 있어 이를 사용해보겠습니다.
rateit.js 를 통한 별점
저번 포스팅과 비슷한 흐름으로 진행됩니다. widgets 에서 커스텀 widget 을 만들고 이를 form에서 연결시켜주도록 하겠습니다. 그리고 그 전에 rateit.js 를 사용하기 위한 파일들을 다운 받아야 합니다. 아쉽게도 CDN 방식을 지원해주지 않아 직접 다운 받도록 했습니다.
https://github.com/gjunge/rateit.js
다운 받은 파일들을 아래와 같은 구조에 위치하였습니다.
# core/forms.py
from django import forms
from .models import University, Student
from .widgets import CounterTextInput, starWidget
# 생략
class StudentForm(forms.ModelForm):
class Meta:
meodel = Student
fields = '__all__'
widgets = {
'grade': starWidget,
}
아직 만들지는 않았지만 starWidget
을 만들어 widget으로 지정해주겠습니다.
<!-- star_rate.html -->
{% load static %}
{% include "django/forms/widgets/input.html" %}
<!-- <link rel="stylesheet" href="{% static 'widgets/rateit/rateit.css' %}">
<script
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous"></script>
<script src="{% static 'widgets/rateit/jquery.rateit.min.js' %}" ></script> -->
{{ form.media }}
<div id="star_{{ widget.attrs.id }}" class="rateit" data-rateit-backingfld="#{{ widget.attrs.id }}"></div>
위에서 다운받은 js, css 외에 이를 사용하기 위해 jqurey 도 CDN 방식으로 가져왔습니다. 그리고 위 주석과 같이 이들을 적어주어야 하지만 {{ form.media }}
를 통해 widgets.py 에서 미리 지정을 해두고 불러올 수 있습니다.
다음으로 기존의 input.html
을 include 하면 input 태그가 존재합니다. 하지만 우리는 별표로 점수를 매길 것이기 때문에 input 태그는 눈에 보이지 않고 별표만 보여야 합니다. data-rateit-backingfld
를 통해 별표로 지정한 값을 어느 input 에 전달할 지 결정할 수 있습니다.
<input type="rating" name="grade" value="4" required="" id="id_grade" min="0" max="5" step="1" style="display: none;">
<div id="star_id_grade" class="rateit rateit-bg" data-rateit-backingfld="#id_grade">
<!-- 생략 -->
</div>
그리고 그 Input 은 위와 같이 자동으로 display: none;
이 됩니다.
from django import forms
# 생략
class starWidget(forms.TextInput):
input_type = 'rating'
template_name = "widgets/star_rate.html"
class Media:
css = {
'all': [
'widgets/rateit/rateit.css',
],
}
js = [
"//code.jquery.com/jquery-3.4.1.min.js",
'widgets/rateit/jquery.rateit.min.js',
]
def build_attrs(self, *args, **kwargs):
attrs = super().build_attrs(*args, **kwargs)
attrs.update({
'min': 0,
'max': 5,
'step': 1,
})
return attrs
기존의 forms.TextInput
을 커스텀한 starWidget
입니다. rateit.js 설명을 보면 input_type
을 rating
으로 할 시에 min
,max
,step
의 설정을 줄 수 있다고 합니다. 말그래도 최소값, 최대값, 한 스텝 당 몇 개의 별씩 증가시킬지에 대한 사항입니다.
또한 Media 클래스에서 css 와 js 에 대해 해당 경로를 지정해줌으로서 위처럼 {{ form.media }}
로 불러 올 수 있습니다.
# core/admin.py
from django.contrib import admin
from .models import University, Student
from .forms import UniversityForm, StudentForm
# 생략
@admin.register(Student)
class StudentAmin(admin.ModelAdmin):
form = StudentForm
마지막으로 admin 에 등록해주면 아래 이미지 처럼 별표를 볼 수 있습니다. 별표의 크기, 모양 , 갯수 등 여러 커스텀이 가능하니 위 다운로드 받은 링크를 참조하거나 댓글 남겨주시면 도와드리겠습니다.