안녕하세요. Toni입니다.
베이비스푼을 개발하고 사용자가 늘어나면서 운영에 필요한 지표들을 확인하고 싶은 needs가 생겼어요.
Flutter & Django로 개발된 베이비스푼의 관리자 페이지를 Django-jet를 이용하여 만들면서 필요한 내용들을 정리해보려 합니다.
다음과 같은 내용들을 차례차례 작성해보려 합니다.
1. Django JET가 무엇인가?
2. Django 장고 템플릿 문법
3. Custom Django Admin page 장고 관리자 페이지 커스텀하기
4. ChartJS 사용법
5. Django Admin page에 차트 그리기
Django JET가 무엇인가?
Django-jet는 장고를 사용하는 프로젝트에서 관리자 기능을 간편하게 제공하는 라이브러리라고 이해하면 될듯합니다.
간단한 설정만으로도 반응형 관리자 페이지를 사용할 수 있지요.
라이선스는 오픈소스(AGPLv3)와 상용 라이선스로 구분되어지고 개별적인 용도로 사용하기엔 무리 없습니다.
우선 Django JET를 설치해야겠지요
pip install django - jet
다음으로 장고 프로젝트의 settings.py 파일에서 jet를 추가하고
TEMPLATE에 django.template .context_processors.request 가 추가되었는지 확인합니다.
INSTALLED_APPS = (
...
'jet',
'django.contrib.admin',
...
)
...
TEMPLATES = [
{
'BACKEND' : 'django.template.backends.django.DjangoTemplates' ,
'DIRS' : [],
'APP_DIRS' : True ,
'OPTIONS' : {
'context_processors' : [
...
'django.template .context_processors.request' ,
...
],
},
},
]
urls.py 파일에 URL 패턴을 추가합니다.
urlpatterns = patterns (
'' ,
url(r'^jet/', include('jet.urls', 'jet')), # Django JET URLS
url(r'^admin/', include(admin.site.urls)),
...
)
DB에 jet와 관련된 테이블을 생성하고
python manage.py migrate jet
다음 명령어를 통해 장고 프로젝트의 각각의 app에서 사용되는 static 파일을 복사합니다.
python manage.py collectstatic
Django 장고 템플릿 문법
장고 템플릿은 단순한 텍스트 파일이며 data를 전달받아 화면에 표시하는 역할을 합니다.
1. 주석
주석은 {# 주석 #} 과 같은 형식으로 사용합니다.
2. 변수
변수는 {{ 변수 }} 와 같은 형식으로 사용합니다. 변수명은 영문자와 밑줄("_") 그리고 점(".")을 사용할 수 있고 공백이나 특수문자는 사용할 수 없습니다.
점(".")은 변수의 속성에 접근하는 용도입니다.
변수가 존재하지 않는 경우 default값은 공백('') 입니다.
{{ user }}
{{ user.name }}
3. 태그 (기본 제공 태그)
태그는 {% 태그 %} 와 같은 형식으로 사용합니다.
태그에는 autoescape나 if와 for 등의 조건들이 기본으로 제공됩니다.
{# False가 아닌 첫번째 변수를 찾아 출력하고 True인 변수가 없으면 "Not found"를 출력 #}
{% firstof var1 var2 var3 "Not Found" %}
{# user_list에 있는 모든 user의 name 표시 #}
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
{# points의 하위 값 x,y 를 각각 사용할 수 있음 #}
{% for x, y in points %}
There is a point at {{ x }},{{ y }}
{% endfor %}
{# if 태그 사용법 3가지, if and, if not, if or #}
{% if athlete_list and coach_list %}
Both athletes and coaches are available.
{% endif %}
{% if not athlete_list %}
There are no athletes.
{% endif %}
{% if athlete_list or coach_list %}
There are some athletes or some coaches.
{% endif %}
{# with~endwith total변수를 재사용 #}
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}
4. 태그필터 (기본 제공 필터)
필터는 파이프("|") 문자를 사용하고 약 60가지의 필터를 제공하고 있습니다. 사용자 정의 필터를 만들어 사용할 수도 있습니다.
필터의 사용법은 다음과 같습니다.
{# value+2 값이 표시 #}
{{ value|add:2 }}
{# name이 false이거나 비어있는 경우 babyspoon 표시 #}
{{ name|default:"babyspoon" }}
{# user의 name 값을 소문자로 변환하여 표시 #}
{{ user.name|lower }}
{# book의 title 변수를 10자만 끊어서 표시 #}
{{ book.title|truncatewords:10 }}
{# list에 있는 값들을 join #}
{# ex, list=["1", "2", "3"] 값이 있는 경우 "1 + 2 + 3"이 표시 #}
"{{ list|join:", " }}"
{# book의 summary가 몇자인지 반환 #}
{{ book.summary|length }}
{# value의 모든 HTML 태그를 제거 #}
{# value 값이 <b>baby</b> spoon <span>is</span> <button>good</button>인 경우 baby spoon is good으로 표시 #}
{{ value|striptags }}
Custom Django Admin page 장고 관리자 페이지 커스텀하기
1. Template에서 사용할 함수 생성 (<앱>/admin.py)
유저 테이블의 app_version별 사용자 수 조회
@admin.site.register_view('user/detail', visible=False)
def user_detail(request):
cursor = connection.cursor()
cursor.execute('''
SELECT app_version, COUNT(id) AS count FROM user GROUP BY app_version ORDER BY app_version DESC;
''')
rows = dictfetchall(cursor)
datas = json.dumps(list(rows), cls=DjangoJSONEncoder)
context = dict(
admin.site.each_context(request),
datas=datas,
)
return render(request, 'admin/user_detail.html', context)
2. Template 만들기, 웹 페이지 구성 (<앱>/templates/admin/user_detail.html)
{% extends 'admin/test.html' %}
{% load humanize %}
{% load static %}
{#{% load define_action %}#}
{% block extrahead %}
{{ block.super }}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const pieContext = document.getElementById('pieChart').getContext('2d');
const barContext = document.getElementById('barChart').getContext('2d');
const chartData = {{ datas | safe }};
var pieData = [];
chartData.forEach((d) => {
d.x = d.app_version;
d.y = d.count;
pieData.push(d.count);
});
const pieChart = new Chart(pieContext, {
. . . // 아래에서 설명
});
const barChart = new Chart(barContext, {
. . . // 아래에서 설명
});
});
</script>
{% endblock %}
{% block content %}
{{ block.super }}
<span class='glyphicon glyhicon-heart'></span>
<h3>유저 AppVersion 정보</h3>
<br>
<div style="width: 30%; height: 150px;">
<table>
<colgroup>
<col style="width:10%">
<col style="width:10%">
</colgroup>
<thead>
<tr>
<th>App Version</th>
<th>Count</th>
</tr>
</thead>
<tbody>
{% for do in rows %}
<tr>
<td>{{ do.app_version }}</td>
<td>{{ do.count }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<br>
<div style="width: 100%; height: 300px;">
<div style="width: 30%; height: 300px; border:1px solid green; float:left; margin-right:10px;">
<canvas style="margin-bottom: 10px; width: 60%; height: 50%;" id="pieChart"></canvas>
</div>
<div style="width: 65%; height: 300px; border:1px solid red; float:left;">
<canvas style="margin-bottom: 10px; width: 60%; height: 50%;" id="barChart"></canvas>
</div>
</div>
{% endblock %}
3. 결과 화면
✻ 해당 결과화면은 베이비스푼 개발서버에 있는 dummy data를 바탕으로 구현된 모습입니다.
ChartJS를 이용하여 Django Admin page에 차트 그리기
ChartJS는 웹에서 차트를 그릴때 가장 많이 사용되는 라이브러리 중 하나입니다. MIT 라이선스를 사용하고 있어요.
ChartJS에서 제공하고 있는 Chart의 종류는 다음과 같습니다.
Area Chart, Bar Chart, Doughnut & Pie Chart, Line Chart, Mixed Chart Types, Polar Area Chart, Radar Chart, Scatter Chart
각각의 용도에 따라 차트를 선택적으로 사용하면 되겠습니다.
위에서 봤듯이 저는 가장 많이 사용하는 PieChart와 BarChart를 이용하여 버전별 사용자 수를 한눈에 파악할 수 있도록 했습니다.
PieChart와 BarChart의 설정은 아래와 같습니다.
PieChart에서는 각 버전별 색상을 지정하여 구분이 될 수 있도록 했고 BarChart에서는 y축의 max값을 지정하여 사용했습니다.
const pieChart = new Chart(pieContext, {
type: 'pie',
data: {
labels: [
"1.4.0",
"1.3.7",
"1.3.6",
"unknown",
],
datasets: [
{
data: pieData,
backgroundColor: [
'rgb(162, 205, 86)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)',
'rgb(220,20,20,0.5)',
],
hoverOffset: 4
},
],
},
});
const barChart = new Chart(barContext, {
type: 'bar',
data: {
labels: [
"1.4.0",
"1.3.7",
"1.3.6",
"unknown",
],
datasets: [
{
label: 'user count',
data: chartData,
backgroundColor: 'rgba(220,20,20,0.5)',
},
],
},
options: {
responsive: true,
scales: {
yAxes: [
{
ticks: {
max: 2000,
beginAtZero: true,
},
},
],
},
},
});
관리자 페이지를 만들면서 추가적으로 정리할만한 내용이 생기면 업데이트 하겠습니다.
감사합니다.
도움이 된 사이트
1. django 기본 개념 이해하기 : https://defineall.tistory.com/678
2. Adding charts to Django admin : https://findwork.dev/blog/adding-charts-to-django-admin/
'Development > Django' 카테고리의 다른 글
Python 기본 명령어 모음 (0) | 2022.11.17 |
---|