Django - ExcelCalCulator_5

Page content

개요

  • Django 한 그릇 뚝딱 교재의 내용에서 멀티캠퍼스 강의에 맞게 일부 수정함
  • 2019년 버전이고 현재는 2023년이기 때문에 소스코드 변경 사항이 필요할 거 같아서 글을 남김

교재 홍보

Untitled

Step 01 - 이전 글

Step 02 - 파일 업로드 하기

  • 로그인을 통해 메인 화면으로 왔다면, 파일 업로드 기능 구현

Step 03 - 파일 업로드 기능 구현

check - 1 : index.html 구현

  • 파일 경로 : ExcelCalculate > main > templates > main > index.html
  • 파일 제출 버튼을 눌렀을 때 가려는 url을 등록한다.
  • 또한 enctype="multipart/form-data" 를 추가한다.
    • 이것을 사용해야 파일의 내용이 올바르게 전달된다.
        <div class="content">
            <div class="fileInputDiv">
                <form action="**calculate/**" method="POST" enctype="multipart/form-data">{% csrf_token %}
                    <div class="input-group">
                        하단 버튼을 통해 파일을 업로드 해주세요.(.xls 확장자의 파일만 가능합니다.)<br>
                        <input id="fileInput" name="fileInput" type="file" class="form-control">
                        <input type="submit" class="btn btn-success btn-lg" value="파일 제출">
                    </div>
                </form>
            </div>
        </div>
  • calculate/ 경로는 초기에 ExcelCalculate > ExcelCalculate > urls.py에서 이미 설정해놨다.
    • 링크 참조 :
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('email/', include('sendEmail.urls'), name="email"), 
    path('calculate/', include('calculate.urls'), name="calculate"),
    path('', include('main.urls'), name="main"),
    path("admin/", admin.site.urls),
]
  • ExcelCalcalculate > calculate > urls.py 에서도 이미 설정을 해놨다.
from django.urls import path
from . import views

urlpatterns = [
    path('', views.calculate, name="calculate_do"), 
]

check - 2 : views.py 구현

  • 파일 경로 : ExcelCalculate > calculate > views.py
  • 이 때, request.POST가 아닌 request.FILES를 이용한다.
# Create your views here.
def calculate(request):
    file = request.FILES['fileInput']
    print("# 사용자가 등록한 파일의 이름: ", file)
    return HttpResponse("calculate, calculate function!")

check - 3 : 테스트

  • 이제 data.xlsx 파일을 업로드 한다.
  • 파일 제출 버튼을 누를 시, 웹에서는 정상적으로 calculate, calculate function! 출력이 되어야 하고 터미널에서는 아래와 같이 print() 문구가 나와야 한다.

Untitled

Untitled

Untitled

Step 04 - pandas 사용

  • data.xlsx 파일을 분석해 아래 항목들의 값을 구해 볼 것이다.
    • grade별 value 최솟값, 최댓값, 평균값
    • 이메일 도메인 주소별 인원수
  • 함수 처리는 ExcelCalculate > calculate > views.py에서 처리한다.
from django.shortcuts import render, redirect
from django.http import HttpResponse
import pandas as pd

# Create your views here.
def calculate(request):
    file = request.FILES['fileInput']
    print("# 사용자가 등록한 파일의 이름: ", file)
    df = pd.read_excel(file, sheet_name="Sheet1", header=0)
    print(df.head())
    # grade별 value 리스트 만들기
    grade_dic = {}
    total_row_num = len(df.index)
    for i in range(total_row_num):
        data = df.loc[i, :]
        if not data.grade in grade_dic.keys():
            grade_dic[data.grade] = [data.value]
        else:
            grade_dic[data.grade].append(data.value)

    # print(grade_dic)
    # grade별 최솟값 최댓값 평균값 구하기
    grade_calculate_dic = {}
    for key in grade_dic.keys():
        grade_calculate_dic[key] = {}
        grade_calculate_dic[key]['min'] = min(grade_dic[key])
        grade_calculate_dic[key]['max'] = max(grade_dic[key])
        grade_calculate_dic[key]['avg'] = float(sum(grade_dic[key])) / len(grade_dic[key])

    # 결과 출력
    grade_list = list(grade_calculate_dic.keys())
    grade_list.sort()
    for key in grade_list:
        print("# grade: ", key)
        print("min:", grade_calculate_dic[key]['min'], end="")
        print("/ max:", grade_calculate_dic[key]['max'], end="")
        print("/ avg:", grade_calculate_dic[key]['avg'], end="\n\n")

    # 아래 코드와 동일
    result = df.groupby('grade')['value'].agg(["min", "max", "mean"])
    print(result)

    # 이메일 주소 도메인별 인원 구하기
    email_domain_dic = {}
    for i in range(total_row_num):
        data = df.loc[i, :]
        email_domain = data['email'].split("@")[1]
        if not email_domain in email_domain_dic.keys():
            email_domain_dic[email_domain] = 1
        else:
            email_domain_dic[email_domain] += 1
    print("## EMAIL 도메인별 사용 인원")
    for key in email_domain_dic.keys():
        print("#", key, ": ", email_domain_dic[key], "명")

    df['domain'] = df['email'].apply(lambda x : x.split("@")[1])
    result2 = df.groupby('domain')['value'].agg("count").sort_values(ascending=False)
    print(result2)

    return HttpResponse("calculate, calculate function!")
  • grade별 value 최솟값, 최댓값, 평균값을 구한 결괏값은 다음과 같다.

Untitled

  • 이메일 도메인 주소별 인원수

Untitled