웹페이지에 시각화한 데이터를 보여주기
pip install pandas
데이터 프레임을 생성하고 생성한 데이터 프레임은 맷플롯립으로 그래프를 생성하는데 사용한다.
plotting 은 utils.py
파일에서 다루고, 유틸파일을 뷰 파일에서 사용하도록 한다
utils.py
에 함수 추가하기import base64
import uuid
from .models import *
from io import BytesIO
from matplotlib import pyplot as plt
def generate_code():
return str(uuid.uuid4()).replace('-', '').upper()[:12]
def get_key(res_by):
if res_by == '#1':
key = 'transaction_id'
elif res_by == '#2':
key = 'created'
elif res_by == '#3':
key = 'customer'
elif res_by == '#4':
key = 'total_price'
return key
def get_graph():
buffer = BytesIO()
plt.savefig(buffer, format='png')
buffer.seek(0)
image_png = buffer.getvalue()
graph = base64.b64encode(image_png)
graph = graph.decode('utf-8')
buffer.close()
return graph
def get_chart(chart_type, data, results_by, **kwargs):
plt.switch_backend('AGG')
fig = plt.figure(figsize=(10, 4))
key = get_key(results_by)
d = data.groupby(key, as_index=False)['total_price'].agg('sum')
if chart_type == '#1':
print("Bar Graph")
plt.bar(d[key], d['total_price'])
elif chart_type == '#2':
print("Pie chart")
plt.pie(data=d, x='total_price', labels=d[key])
elif chart_type == '#3':
print("Line graph")
plt.plot(d[key], d['total_price'], color='gray', marker='o', linestyle='dashed')
else:
print("차트 타입이 선택되지 않았습니다")
plt.tight_layout()
chart = get_graph()
return chart
get_chart()
함수가 실행 시
pyplot.switch_backend('AGG')
화면에 플롯팅되는 것을 막는다. 차트를 이미지로 넘길 것이다.
fig
변수
차트의 차원을 정의한다.
key = get_key(results_by)
사용자의 선택에 따라 키 변수를 설정한다. 폼에서의 RESULTS_CHOICE로 받은 내용이다
d = data.groupby(key, as_index=False)['total_price'].agg('sum')
총액을 사용하는 키를 이용하여 데이터를 그룹화한다.
사용자 선택에 따라 차트가 플롯팅된다.
pyplot.tight_layout()
차트의 사이즈를 fig
설정에 따라 맞춘다
차트 변수를 get_graph()
함수를 이용하여 초기화하고 반환한다. 이 메소드는 버퍼를 생성하며 시작된다.
차트는 버퍼에 이미지로 저장된다. 버퍼 내용은 base64.b64encode()
에 의해서 인코딩되고 디코딩되어 반환된다.
views.py
파일 수정import pandas as pd
from django.shortcuts import render
from django.views.generic import ListView
from django.contrib import messages
from .forms import SalesSearchForm
from .models import *
# Create your views here.
from .utils import get_chart
def sales(request):
sales_df = None
chart = None
no_data = None
search_form = SalesSearchForm(request.POST or None)
if request.method == 'POST':
date_from = request.POST.get('date_from')
date_to = request.POST.get('date_to')
chart_type = request.POST.get('chart_type')
results_by = request.POST.get('results_by')
print(date_from, date_to, chart_type)
sales_qs = Sale.objects.filter(created__date__lte=date_to, created__date__gte=date_from)
if len(sales_qs) > 0:
sales_df = pd.DataFrame(sales_qs.values())
print(sales_df)
sales_df['created'] = sales_df['created'].apply(lambda x: x.strftime('%d/%m/%Y'))
sales_df.rename({'customer_id': 'customer', 'salesman_id': 'salesman', 'id': 'sales_id'}, axis=1,
inplace=True)
chart = get_chart(chart_type, sales_df, results_by)
sales_df = sales_df.to_html()
else:
messages.warning(request, "Apparently no data available...")
context = {'search_form': search_form,
'sales_df': sales_df,
'chart': chart, }
return render(request, 'sales.html', context)
POST 요청 받았는지 확인 후, 받았다면 그 값을 변수에 할당한다.
모든 sales를 날짜에 따라 필터링한다. 필터링 후 데이터가 존재한다면 sales 쿼리세트 값을 이용하여 데이터 프레임을 생성한다.
날짜 포매팅
데이터 프레임 열 이름 수정하기
차트를 utils.py에 정의되어 있는get_chart()
를 사용하여 초기화한다. get_chart()
는 차트타입, 영업 데이터프레임, results by values를 변수로 받는다.
영업 데이터를 HTML 포맷으로 변환하여 데이터를 웹 페이지에서 나타낼 수 있도록 한다.
sales.html
파일 수정데이터 프레임과 차트를 나타낼 수 있도록 HTML을 수정한다.
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block title %}
Home
{% endblock title %}
{% block content %}
{% for message in messages %}
<div role="alert" class="alert alert-warning">
{{ message }}
</div>
{% endfor %}
<form action="" method="post">
{% csrf_token %}
{{ search_form|crispy }}
<button class="btn btn-primary mt-3" type="submit">Search</button>
</form>
<hr>
{% if sales_df %}
<b>Sales Dataframe</b>
{{ sales_df|safe }}
<hr>
<hr>
<b>Chart</b>
<img src="data:image/png;base64, {{ chart|safe }}" alt="" id="img">
{% endif %}<br>
{% endblock content %}
python manage.py makemigrations
python manage.py migrate