[Django]장고 veiws.py에서 html로 데이터 값 보이기(for문)

2020. 12. 29. 09:00카테고리 없음

반응형

Django로 웹페이지를 만드는 개발자분들..!

파이썬 문법을 활용하여 원하는 형태로 데이터를 처리한 뒤 html로 데이터를 보내는것에 큰 재미를 느낄것이라 생각이 들어요! 

저도 파이썬 문법으로 쉽게 데이터 전처리도 하고 통계 더 나아가 ML(머신러닝)까지 쉽게 코딩하며 html로 데이터를 보낼 수 있어서 너무 편리했어요

편리하니까 재밌더군요 ㅎㅎ

오늘은 views.py에서 데이터 전처리 후 html에서 값을 출력하는 것을 적어볼려고 해요..!

먼저 결과화면입니다. 

빨간색 선으로 표시된 것을 구현해보려고 해요.

빨간색 선 안에는 tab으로 이뤄져 있고. 

db에서 필요한 데이터들을 for문을 활용하여 화면에 보여주는 방법을 알아보도록 해요~! 

 

먼저 models.py에 있는 데이터 형태부터 보여드릴게요.

Credit이라는 class를 생성했고, 칼럼이 약 33개인 필드를 가진 테이블입니다. 

class Credit(models.Model):
    id = models.AutoField(primary_key=True)
    tdy = models.CharField(max_length=30)
    cmt = models.CharField(max_length=30)
    bond = models.CharField(max_length=30)
    isin = models.CharField(max_length=30)
    country = models.CharField(max_length=30)
    region = models.FloatField()
    currency = models.CharField(max_length=30)
    sector = models.CharField(max_length=100)
    mty_years_tdy = models.FloatField()
    duration = models.FloatField()
    type = models.CharField(max_length=30)
    coupon = models.FloatField()
    rating_md = models.CharField(max_length=30)
    rating_sp = models.CharField(max_length=30)
    rating_ft = models.CharField(max_length=30)
    rating = models.CharField(max_length=30)
    nrate_all = models.FloatField()
    delta_6m  = models.FloatField()
    equity_price  = models.FloatField()
    volume  = models.FloatField()
    cds_5y  = models.FloatField()
    bond_yield = models.FloatField()
    yld_chg_mtd = models.FloatField()
    yld_chg_ytd = models.FloatField()
    g_sprd = models.FloatField()
    bm_sprd = models.FloatField()
    bm_bond = models.CharField(max_length=30)
    yld_sprd= models.FloatField()
    z_sprd_usd = models.FloatField()
    asset_swap_sprd_usd = models.FloatField()
    oas_sprd_usd = models.FloatField()
    govt_mty_sprd_usd = models.FloatField()

 

views.py입니다.

from board.models import *
from django.http import HttpResponse, HttpResponseRedirect
import pandas as pd
import matplotlib.pyplot as plt
import json
from django.core.serializers.json import DjangoJSONEncoder
from datetime import datetime

def index(request):
##models.py에서 데이터를 qeuryset형태로 가져온다! values()안에는 column명을 적어서 특정 칼럼만 가져온다.
	credit_list = Credit.objects.filter(tdy='2020-10-27').values('cmt','tdy', 'bond', 'bond_yield', 'mty_years_tdy', 'nrate_all','g_sprd','bm_sprd','govt_mty_sprd_usd','z_sprd_usd',
                                        'country','region','sector')

#쉽게 전처리를 위한 pandas 변환 부터!
    credit_list_pd = pd.DataFrame.from_dict(credit_list)

#Dataframe특성을 이용한 2차 칼럼 선택	
    ratio = credit_list_pd[['cmt', 'bond', 'country', 'region', 'sector', 'tdy','g_sprd','bm_sprd']]

#region==1(US)인 데이터만 뽑아오기	
    us = ratio[ratio['region'] == 1]

#'cmt'라는 컬럼중에 'Spread' 또는 'Rating'이 포함된 값들만 뽑아오기 
    us_bond_ = us[us['cmt'].str.contains('Spread|Rating')]
    
#중복되는 값들을 버리기(drop)    
    us_bond_b = us_bond_['bond'].drop_duplicates(keep='last')
   
#index를 재설정   
    us_bond_b = us_bond_b.reset_index(drop=True)
   
#html로 보낼때, 저는 json또는 list 데이터 형식으로 보냈어요(다루기가 매우 쉽기때문이었요!)   
    us_bond = list(us_bond_b)


##html로 데이터를 넘기기 위한 포장지 만들기
    context = {
    #html로 보내는 필드명을 ''(따옴표)안에 넣어주면 됩니다.
    	'us_bond':us_bond
    }
 
 
##html로 값을 보내는 부분    
    return render(request, 'board/index.html', context)

 

 

index.html 입니다.

<div class="row col-lg-12">
<!--세계 지도 부분-->   
    <div id="world_container" class="col-lg-6" style="margin-top: -20px;"></div>

<!--탭 시작-->
    <div class="col-lg-6" style=" margin-left: -120px; margin-top:-25px;" >
        <ul class="nav nav-tabs">
            <li class="nav-item active">
                <a class="nav-link" data-toggle="tab" href="#usus">US</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" data-toggle="tab" href="#eu">EU</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" data-toggle="tab" href="#asia">ASIA</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" data-toggle="tab" href="#etc">ETC</a>
            </li>
        </ul>

<!--탭 내용-->
        <div id="my_tab" class="tab-content" >
            <div class="tab-pane fade show active" id="usus">
                <p>
                    {% for item in us_bond %}
                    ({{ forloop.counter }}) {{item}}<br/>
                    {% endfor %}
                </p>
            </div>
            
            <div class="tab-pane fade" id="eu">
                <p>
                    {% for eu in eu_bond %}
                    ({{ forloop.counter }}) {{eu| safe}}
                    <br/>
                    {% endfor %}
                </p>
            </div>
            
            <div class="tab-pane fade" id="asia">
                <p>
                    {% for asia in asia_bond %}
                    ({{ forloop.counter }}) {{asia| safe}}
                    <br/>
                    {% endfor %}
                </p>
            </div>
            
            <div class="tab-pane fade" id="etc">
                <p>
                    {% for etc in etc_bond %}
                    ({{ forloop.counter }}) {{etc| safe}}
                    <br/>
                    {% endfor %}
                </p>
            </div>

        </div>
        <br/>
        <div style="text-align: right"><h7 style="margin-left: 60px;">※ 상세 내용은 [Credit List] Tab 확인 가능</h7></div>
    </div>

</div>

위 코드를 보면, 탭 관련 bootstrap 코드입니다 :) 

메뉴탭<->내용부분을  href="#usus"과 id="usus" 연결시켜서 코딩을 하면 됩니다.

그리고 django에는 html에서 쓰는 "template언어"가 있어요.

{} 이런 괄호를 써서 html 내 문법에서 존재를 알려줘야 합니다.

{} 안에 문법은 나름(?) python언어와 비슷해서 python언어를 많이 써보신분들은 금방 익히실 수 있을거에요.

{% for item in  items %}

{{i tem }}

{% endfor %}

위에 코드에서 보듯이 이렇게 veiws.py에서 넘어온 list나 json 형태의 데이터를 

for문을 통해 뽑아서 보여줄 수 있습니다.

{{ forloop.counter }}  이 문법은 for문을 돌면서 숫자를 세는 문법이에요 

{{eu| safe}}   여기 템플릿 변수 다음에 바('|')를 그은 다음 적용하고자 하는 '필터'를 명시한다고 합니다.

json데이터를 쓸때 safe 필터를 사용하는 예제를 많이 보았는데요, tag escape를 방지할 수 있다고 합니다.

tag escape가 처음엔 뭔지 ...했지만, 

html에서 json 데이터를 가져올 때 tag로 인식해서 가져오는경우가 있다고 하더라구요.

이것을 방지하기 위해 |safe라는 내장 필터를 적어주는게 좋다고 합니다 ㅎㅎ!