본문 바로가기
Python/Django

[django] 입력값과 일치하는 것들에 수식 넣기

by zenna 2022. 5. 10.
728x90

목표 : 
음식 이름을 입력하면 일치하는 항목을 찾아
해당 음식의 중량 대비 kcal, 탄수화물, 지방 등의 영양 정보를 계산하고
sql에 합계값을 저장하도록 합니다

 

프로젝트 진행 중, AI가 사진을 분석한 결과값(음식 이름, 중량)을 리턴해주면

값을 정제하여 MySQL에 저장해주는 기능이 필요해졌습니다. 

 

일단 음식 이름과 중량 대비 영양소가 어느정도인지 기준 데이터가 필요합니다. 

데이터는 AI Hub에 있는 '영양성분 데이터'를 사용하기로 했습니다. 

데이터는 아래처럼 구성되어 있어요.

MySQL에 이 데이터를 넣으려 합니다. 

먼저 테이블을 생성해야 하는데 저희 프로젝트는 django를 프레임워크로 사용하므로 django의 models를 사용하여 생성해 주기로 합니다. 

컬럼 이름이 참 직관적이죠..? ^_^...

migrate해줍니다.

잘 생성됐습니다. 

이제 여기에 데이터를 집어 넣기 위해 가공을 좀 해줍니다. 

1. 맨 앞에 숫자로 된 id컬럼을 추가하고 1~숫자를 넣어줍니다

2. 다른이름으로 저장 - 인코딩은 ANSI, 파일 형식은 csv로 바꿔줍니다.

왜 인코딩을 ANSI로 해야하는지는 모르겠어요. 다른 형식은 MySQL에서 뱉어내요.

 

이제 table data import wizard를 이용해 데이터를 넣어주겠습니다. 

다른 좋은 방법이 있을지 모르겠지만..전 이렇게 해요...

데이터를 다 넣고 나면

쫘란


이제 데이터는 준비됐습니다. 

사진은 꽃이지만... 아직 AI가 구현이 안되어서그래요.. 저 꽃을 설렁탕 600g으로 인식했다고 치고 작업하겠습니다.

html상에서 회색 테이블(AI가 분석한 결과물)은 

<input type="text" name="ai_1" />
<input type="text" name="ai_g1"/>

이렇게 받아옵니다. 첫번째 음식명은 ai_1, 중량은 ai_g1

두번째 음식명은 ai_2, 중량은 ai_g2 식으로요.

 

하얀 테이블은 사용자가 사진상에 나오지 않은 음식을 직접 추가할 수 있도록 만든 곳이에요.

음식 이름과 중량을 입력하면

첫번째 음식은 sl_1, 중량은 sl_g1

두번째 음식은 sl_2, 중량은 sl_g2 ... 식으로 받아옵니다. 

 

html전체 코드를 보고 싶으시면 아래 더보기 버튼을 클릭하시면 됩니다!

더보기
<div class="row">
    <div class="col-md-4 ml-auto ar-auto" style="text-align: center">
        <img src="/media/{{k_hc.uploadedFile}}" style="object-fit: contain; width: 90%;" />

    </div>



    <!-- 화면 반 나누기 -->
    <div class="col-md-8 ">
        <div class="row d-flex flex-column h-100">
            <!-- ============폼 시작================ -->
            <form action="/ph/f_uploading" method="POST" enctype="multipart/form-data">
                {% csrf_token %}

                <div class="row">
                    <!-- 연도 월일 식사 종류 선택 -->
                    <div class="col-md-3 ml-auto ar-auto" style="margin: 1em auto 1em auto">
                        <input name="date" type="date" id="currentDate" class="form-control"/>

                        <script>
                        document.getElementById('currentDate').value = new Date().toISOString().substring(0, 10);;
                        </script>

                        <br>
                        <select name="time" class="form-select" aria-label="Default select example">
                            <option value=" " selected>식사 종류 선택</option>
                            <option value="아침">아침</option>
                            <option value="점심">점심</option>
                            <option value="저녁">저녁</option>
                            <option value="기타">기타</option>
                        </select>
                    </div>

                    <!-- 사진 찍은 음식 저장 -->
                    <div class="col-md-9" style="padding: 15px;">
                        <table class="food" style="text-align: center; width: 87%">
                            <tr>
                                <th style="width: 20%">NO.</th>
                                <th style="width: 50%">음식이름</th>
                                <th style="width: 30%">중량</th>
                            </tr>
                            <tr>
                                <td>1</td>
                                <td>
                                    <input type="text" name="ai_1" value="설렁탕"/>
                                </td>
                                <td>
                                    <input type="text" name="ai_g1" value="600" style="width:80%"/>g
                                </td>
                            </tr>
                        </table>
                    </div>

                </div>
                <!-- 아래 위로 공간 나누기 -->
                <div class="row">
                    <div class="col-md-12 h-100">

                        <!-- 부족한 음식 입력 -->
                        <!-- <button onclick="zen_hideorseek('input_theirself')" class="btn btn-outline-light btn-dark" style="float: right;">
                            직접 입력하기
                        </button> -->
                        <br>
                        <div id="input_theirself" style="display: block;">
                            <table style="border: 1px rgb(14, 13, 13) solid; width: 90%; color: black; text-align: center;">
                                <tr>
                                        <th style="width: 10%">NO.</td>
                                        <th style="width: 50%">음식 이름</td>
                                        <th style="width: 40%">중량(g)</td>
                                        <!-- <th style="width: 25%">Value</td> -->
                                </tr>
                                <tr>
                                    <td>1</td>
                                    <td><input type="text" name="sl_1"></td>
                                    <td><input type="number" name="sl_g1">g</td>
                                    <!-- <td></td> -->
                                </tr>
                                <tr>
                                    <td>2</td>
                                    <td><input type="text" name="sl_2"></td>
                                    <td><input type="number" name="sl_g2">g</td>
                                    <!-- <td></td> -->
                                </tr>
                                <tr>
                                    <td>3</td>
                                    <td><input type="text" name="sl_3"></td>
                                    <td><input type="number" name="sl_g3">g</td>
                                    <!-- <td></td> -->
                                </tr>
                                <tr>
                                    <td>4</td>
                                    <td><input type="text" name="sl_4"></td>
                                    <td><input type="number" name="sl_g4">g</td>
                                    <!-- <td></td> -->
                                </tr>
                            </table>
                        </div>
                    </div>
                </div>

                <!-- 다 작성하고 제출하기 -->
                <div class="row">
                    <div class="col-md-12 h-100">
                        <footer style="text-align: right;">
                            <input name='file_location' type="hidden" value="{{k_hc.uploadedFile}}">
                            <input type="hidden" value="{{idx}}" name="idx"/>
                            <input type="submit" value="작성완료" class="btn btn-outline-light btn-dark"/>
                        </footer>
                    </div>
                </div>  
            </form>
        </div>
    </div>
</div>

 

이제 받아온 input들을 처리해줘야 합니다. 

 

일단 가공할 필요 없는 input들을 저장해주는 코드를 먼저 짭니다. 

[views.py]

def f_upload_at_sql(request):
    idx = request.POST['idx']
    date=request.POST['date']

    diets = diet()
    diets.user_id = request.POST['idx']
    diets.date=request.POST['date']
    diets.time = request.POST['time']
    diets.foodimage = request.POST['file_location']
    
    diets.save()

    return redirect('/m/'+idx+'/'+date)

 

다음으로는 입력된 음식 이름과 중량을 이중 리스트로 받아오기 위한 for 구문을 짭니다.

 

views.py

menulist = []
for i in range(1, 2):
    try:
        if (request.POST['ai_{}'.format(i)] != ''):
            # print(request.POST['ai_{}'.format(i)])            
            menulist.append([(request.POST['ai_{}'.format(i)]),int(request.POST['ai_g{}'.format(i)])])
    except : print('첫번째가 이;상해')
for i in range(1, 5):
    try:
        if (request.POST['sl_{}'.format(i)] != ''):
            # print(request.POST['sl_{}'.format(i)])            
            menulist.append([(request.POST['sl_{}'.format(i)]),int(request.POST['sl_g{}'.format(i)])])
    except : print('2번째가 이상하대')

저도 이게 될 줄 몰랐어요.

루프 안에서, 각 인풋이 빈칸이 아니라면 menulist에 추가하도록 해서 최종적으로 menulist에 아래 인풋이 이중 배열 형식으로 저장되게 했습니다.

AI 분석 결과를 메뉴 2개까지 받아올 수 있도록 설정해두었는데

메뉴가 하나뿐이면 에러가 날까봐 try - except구문을 만들어 두었는데 딱히 에러가 안 났네요.

여기까지 하고 나면 

위 화면처럼 입력했을 때 아래 모양의 이중 리스트로 값을 저장합니다. 

 

이제 리스트에 저장된 메뉴 이름과 중량을 토대로 총 kcal를 받아와야합니다. 

nutrlist = {'kcal':0,'tan':0,'dang':0,'ji':0,'dan':0,'kalsum':0,'inn':0,'salt':0,'kalum':0, 'magnesum':0, 'chul':0,'ayeon':0,'kolest':0,'transfat':0} #빈 딕트 선언

for i in range(0, len(menulist)) :
    # print('menulist',menulist[i][0])
    datalist = get_object_or_404(menu, food_name=menulist[i][0])
    nutrlist['kcal'] = nutrlist['kcal'] + (datalist.kcal / datalist.basic_g * menulist[i][1])
    nutrlist['tan'] = nutrlist['tan'] + (datalist.tan / datalist.basic_g * menulist[i][1])
    nutrlist['dang'] = nutrlist['dang'] + (datalist.dang / datalist.basic_g * menulist[i][1])
    nutrlist['ji'] = nutrlist['ji'] + (datalist.ji / datalist.basic_g * menulist[i][1])
    nutrlist['dan'] = nutrlist['dan'] + (datalist.dan / datalist.basic_g * menulist[i][1])
    nutrlist['kalsum'] = nutrlist['kalsum'] + (datalist.kalsum / datalist.basic_g * menulist[i][1])
    nutrlist['inn'] = nutrlist['inn'] + (datalist.inn / datalist.basic_g * menulist[i][1])
    nutrlist['salt'] = nutrlist['salt'] + (datalist.salt / datalist.basic_g * menulist[i][1])
    nutrlist['kalum'] = nutrlist['kalum'] + (datalist.kalum / datalist.basic_g * menulist[i][1])
    nutrlist['magnesum'] = nutrlist['magnesum'] + (datalist.magnesum / datalist.basic_g * menulist[i][1])
    nutrlist['chul'] = nutrlist['chul'] + (datalist.chul / datalist.basic_g * menulist[i][1])
    nutrlist['ayeon'] = nutrlist['ayeon'] + (datalist.ayeon / datalist.basic_g * menulist[i][1])
    nutrlist['kolest'] = nutrlist['kolest'] + (datalist.kolest / datalist.basic_g * menulist[i][1])
    nutrlist['transfat'] = nutrlist['transfat'] + (datalist.transfat / datalist.basic_g * menulist[i][1])

1. 여러 음식의 합계를 저장할 빈 딕트를 하나 생성

2. 해당 키에 더할 값 = 기준영양소 / 기준중량 X 실제 먹은 중량

..인데 for루프로 만들어서 줄여보려고 했는데 잘 안됐어요.

아래는 실패한 시도..

더보기
listx = ['kcal','tan','dang','ji','dan','kalsum','inn','salt','kalum', 'magnesum', 'chul','ayeon','kolest','transfat']
       
for j in range (0,len(listx)) :
    print('what==============',listx[j])
    nutrlist[listx[j]] = nutrlist[listx[j]] + (datalist.listx[j] / datalist.basic_g * menulist[i][1])
    print('제대로 계산이 될까? ========',nutrlist)

쨌든, 이 구문을 거치고 나면

이런 모양으로 모든 음식의 영양소를 합친 딕트가 생성이 됩니다.

이제 이 딕트를 MySQL의 해당 컬럼에 저장해주기 위해서

    diets.kcal = nutrlist['kcal']
    diets.tan = nutrlist['tan']
    diets.dang =nutrlist['dang'] 
    diets.ji =nutrlist['ji']
    diets.dan =nutrlist['dan']
    diets.kalsum =nutrlist['kalsum']
    diets.inn =nutrlist['inn']
    diets.salt =nutrlist['salt'] 
    diets.kalum =nutrlist['kalum']
    diets.magnesum =nutrlist['magnesum']
    diets.chul =nutrlist['chul'] 
    diets.ayeon =nutrlist['ayeon'] 
    diets.kolest =nutrlist['kolest'] 
    diets.transfat =nutrlist['transfat']

해주면 끝납니다.

views.py의 전체 코드는 아래 더보기를 클릭 해 주세요

더보기
def f_upload_at_sql(request):
    idx = request.POST['idx']
    date=request.POST['date']

    menulist = []
    for i in range(1, 2):
        try:
            if (request.POST['ai_{}'.format(i)] != ''):
                # print(request.POST['ai_{}'.format(i)])            
                menulist.append([(request.POST['ai_{}'.format(i)]),int(request.POST['ai_g{}'.format(i)])])
        except : print('첫번째가 이;상해')
    for i in range(1, 5):
        try:
            if (request.POST['sl_{}'.format(i)] != ''):
                # print(request.POST['sl_{}'.format(i)])            
                menulist.append([(request.POST['sl_{}'.format(i)]),int(request.POST['sl_g{}'.format(i)])])
        except : print('2번째가 이상하대')

    diets = diet()
    diets.user_id = request.POST['idx']
    diets.date=request.POST['date']
    diets.time = request.POST['time']
    diets.foodimage = request.POST['file_location']
    
    nutrlist = {'kcal':0,'tan':0,'dang':0,'ji':0,'dan':0,'kalsum':0,'inn':0,'salt':0,'kalum':0, 'magnesum':0, 'chul':0,'ayeon':0,'kolest':0,'transfat':0} #빈 딕트 선언

    for i in range(0, len(menulist)) :
        # print('menulist',menulist[i][0])
        datalist = get_object_or_404(menu, food_name=menulist[i][0])
        nutrlist['kcal'] = nutrlist['kcal'] + (datalist.kcal / datalist.basic_g * menulist[i][1])
        nutrlist['tan'] = nutrlist['tan'] + (datalist.tan / datalist.basic_g * menulist[i][1])
        nutrlist['dang'] = nutrlist['dang'] + (datalist.dang / datalist.basic_g * menulist[i][1])
        nutrlist['ji'] = nutrlist['ji'] + (datalist.ji / datalist.basic_g * menulist[i][1])
        nutrlist['dan'] = nutrlist['dan'] + (datalist.dan / datalist.basic_g * menulist[i][1])
        nutrlist['kalsum'] = nutrlist['kalsum'] + (datalist.kalsum / datalist.basic_g * menulist[i][1])
        nutrlist['inn'] = nutrlist['inn'] + (datalist.inn / datalist.basic_g * menulist[i][1])
        nutrlist['salt'] = nutrlist['salt'] + (datalist.salt / datalist.basic_g * menulist[i][1])
        nutrlist['kalum'] = nutrlist['kalum'] + (datalist.kalum / datalist.basic_g * menulist[i][1])
        nutrlist['magnesum'] = nutrlist['magnesum'] + (datalist.magnesum / datalist.basic_g * menulist[i][1])
        nutrlist['chul'] = nutrlist['chul'] + (datalist.chul / datalist.basic_g * menulist[i][1])
        nutrlist['ayeon'] = nutrlist['ayeon'] + (datalist.ayeon / datalist.basic_g * menulist[i][1])
        nutrlist['kolest'] = nutrlist['kolest'] + (datalist.kolest / datalist.basic_g * menulist[i][1])
        nutrlist['transfat'] = nutrlist['transfat'] + (datalist.transfat / datalist.basic_g * menulist[i][1])

    diets.kcal = nutrlist['kcal']
    diets.tan = nutrlist['tan']
    diets.dang =nutrlist['dang'] 
    diets.ji =nutrlist['ji']
    diets.dan =nutrlist['dan']
    diets.kalsum =nutrlist['kalsum']
    diets.inn =nutrlist['inn']
    diets.salt =nutrlist['salt'] 
    diets.kalum =nutrlist['kalum']
    diets.magnesum =nutrlist['magnesum']
    diets.chul =nutrlist['chul'] 
    diets.ayeon =nutrlist['ayeon'] 
    diets.kolest =nutrlist['kolest'] 
    diets.transfat =nutrlist['transfat']

    diets.save()
    
    return redirect('/m/'+idx+'/'+date)

실제 움직이는 모양은 아래 영상으로 참고해주세요~

 

 

728x90

댓글