웹프로그래밍/Django

[Django] widget (2) widget 만들어보기 - 별점 주기 rateit.js

ssung.k 2019. 8. 22. 03:18

widget (1)

 

[Django] widget (1) widget의 원리와 widget 만들어보기 - 실시간 글자수 표시 widget

input 태그는 type 속성에 따라 여러 모습을 보여줍니다. text 일 때는 글을 입력할 수 있도록, date 일 때는 날짜를 지정할 수 있도록, password 일 때는 비밀번호를 입력할 수 있도록 하는 등 다양한 type이 있..

ssungkang.tistory.com

위의 포스팅과 개별적인 내용이지만 전체적인 내용은 이어지므로 이해가 잘 가지 않는다면 위 포스팅을 참고해주시면 감사하겠습니다.

위 포스팅에서도 확인가능하듯 현재 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_typerating 으로 할 시에 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 에 등록해주면 아래 이미지 처럼 별표를 볼 수 있습니다. 별표의 크기, 모양 , 갯수 등 여러 커스텀이 가능하니 위 다운로드 받은 링크를 참조하거나 댓글 남겨주시면 도와드리겠습니다.

admin Page