반응형
SMALL

오늘의 목표 : 사진 안나오니까 사진 첨부해서 나오게 하기!


1. 초기 상태

jsp로 연결되어 있었던 파일들을 전부 html로 수정하였다.

연결시켰던 상품 등록 input 에 파일을 추가하고, 그걸 DB로 받아오게 한다.

 

2. img 카테고리 만들기

귀찮으니까 쿼리문 안쓰고 그냥 sql에 등록

img 추가

 

3. input 타입 file 추가

파일 DB에 올리는 코드 추가. 

이미 table을 감싸는 form에 encodetype까지 설정 해둠.

<form action="add_product" method="post" name="add_product" id="add_product" enctype="multipart/form-data">

△form 태그 action

<tr>
    <th>* 이미지 업로드</th>
    <td><input type="file" name='file' id='file' maxlength="500" style="width:50%;">             
    <input type="hidden" name='product_ip' value="<%=request.getRemoteAddr()%>"> </td>
</tr>

△원래 코드

<tr>
    <th>* 이미지 업로드</th>
    {% csrf_token %}           
    <td><input type="file" name='file1' id='file1' maxlength="500" style="width:50%;"></td>
</tr>

바뀐 코드

 

4. add_product에 추가(view.py)

원래 add_product는 product_info에 담아 데이터를 보내는데에 썼다.

그 데이터에 파일도 추가해야하는데, 그 파일의 파라미터를 처리하는 if문이 필요하다. -> 파일 업로드 링크에 저장

DB에는 단순히 파일의 이름만 들어간다.

 

@csrf_exempt
def add_product(request):
    product_info = (request.POST['product_name'],
                    request.POST['category_gender_id'], request.POST['category_type_id'],
                    request.POST['buy_price'], request.POST['sell_price'],
                    request.POST['product_info'], request.POST['stock'], request.POST['buy_place'])
    product_insert(product_info)
    return redirect('/shoppingmallPrj/manager')

△원래 코드

# 업로드 링크
UPLOAD_DIR = '/home/kosmo_03/PycharmProjects/myapps/shoppingmallPrj/static/upload/'


@csrf_protect
def add_product(request):

    if 'file1' in request.FILES:
        # 파라미터 처리
        file = request.FILES['file1']
        file_name = file.name  # 첨부파일 이름

        # 파일 오픈 - wb모드(binary)
        fp = open("%s%s" % (UPLOAD_DIR, file_name), 'wb')

        # 파일을 1바이트씩 조금씩 읽어서 저장
        for chunk in file.chunks():
            fp.write(chunk)
        fp.close()  # 파일 닫기

    else:
        file_name = '-'

    product_info = (request.POST['product_name'],
                    request.POST['category_gender_id'], request.POST['category_type_id'],
                    request.POST['buy_price'], request.POST['sell_price'],
                    request.POST['product_info'], request.POST['stock'], request.POST['buy_place'], file_name)
    product_insert(product_info)
    return redirect('/shoppingmallPrj/manager', {'file_name': file_name})

바뀐 코드

 

5. model.py 수정

파일 이름이 컬럼으로 추가되었으므로, insert 데이터를 9개로 늘려준다.

 

def product_insert(product_info):
    print(product_info)
    conn = ora.connect(database)
    cursor = conn.cursor()
    sql = "insert into product_info values(Product_info_seq.nextVal, :1,:2,:3,:4,:5,:6,:7,:8)"
    cursor.execute(sql, product_info)
    cursor.close()
    conn.commit()
    conn.close()

△원래 코드

def product_insert(product_info):
    print(product_info)
    conn = ora.connect(database)
    cursor = conn.cursor()
    sql = "insert into product_info values(Product_info_seq.nextVal, :1,:2,:3,:4,:5,:6,:7,:8,:9)"
    cursor.execute(sql, product_info)
    cursor.close()
    conn.commit()
    conn.close()

바뀐 코드

 

6. 결과

이미지가 잘 들어간다.

이미지가 설정했던 경로에 추가됨

 

7. 상품 세부 내역에 첨부파일 연결

첨부파일 자리에 엑박이 뜬다.

 

파일이 추가되었다. 어차피 DB에는 이름만 저장되어있으므로, 그 이름만 꺼내오면 사진이 꺼내질 것이다.

img 태그로 사진을 불러오자.

 

원래는 jsp 파일이기 때문에  {% for %}를 사용해서 i라는 변수를 출력, 모든 컬럼값들이 차례대로 나오게 했다.

사진까지 추가되었으므로 이미지 파일은 따로 출력하게 하고, 헤드라인도 출력값에 맞게 맞춰준다.

                    <div class="shop__cart__table">
                        <table>
                            <thead>
                                <tr>
                                    <th>상품명</th>
                                    <th>입고가</th>
                                    <th>판매가</th>
                                    <th>매입처</th>
                                    <th>입고</th>
									<th>재고</th>
									<th>재입고여부</th>							
									<th>파일이름</th>
									<th>파일용량</th>
                                </tr>
                            </thead>

                            <tbody>
                            	<c:forEach items="${product_infoList }" var="product_detail">
                            	{% for p in product_detail%}
                                <tr>
                                {% for i in p%}
									<td>{{i}}</td>
                                  {% endfor%}
									<td>
										<c:choose>
											<c:when test="${product_info.product_fsize==0}">첨부파일 없음</c:when>
					    					<c:otherwise>
                                  				<img src="resources/upload/${product_info.product_fname}" width='50'>
                                  			</c:otherwise>
									 	</c:choose>
									</td>
									<td>${product_info.product_fsize}byte</td>
                                </tr>
                                {% endfor %}
                                </c:forEach>
                        </table>
                   </div>

△원래 코드

                    <div class="shop__cart__table">
                        <table>
                            <thead>
                                <tr>
                                    <th>번호</th>
                                    <th>상품명</th>
                                    <th>성별</th>
                                    <th>옷타입</th>
                                    <th>입고가</th>
                                    <th>판매가</th>
                                    <th>입고</th>
                                    <th>재고</th>
                                    <th>매입처</th>
                                    <th>파일이름</th>
                                    <th>이미지</th>
                                </tr>
                            </thead>
							
                               {% for p in product_detail%}
                                   <tr>
                                    {% for i in p%}
                                    <td>{{i}}</td>
                                  {% endfor%}
                                  
                                  <!-- 이미지파일 출력 -->
                                       <td><img src="{{baseUrl}}/upload/{{p.9}}" width='50'></td>
                                   </tr>
                                {% endfor %}

                        </table>
                   </div>

바뀐 코드

사진이 잘 나온다

8. 쇼핑하기 기능에서 사진 띄우기

사진이 나오게 코드를 수정해주자.

모델에서 img 파일을 불러온다고 하지 않았기 때문에 img를 추가해주어야한다.

def getProduct():
    conn = ora.connect(database)
    cursor = conn.cursor()
    sql = "select product_id, product_name, sell_price from product_info order by product_id"
    cursor.execute(sql)
    result = cursor.fetchall()
    cursor.close()
    conn.close()
    return result

△원래 코드

def getProduct():
    conn = ora.connect(database)
    cursor = conn.cursor()
    sql = "select product_id, product_name, sell_price, img from product_info order by product_id"
    cursor.execute(sql)
    result = cursor.fetchall()
    cursor.close()
    conn.close()
    return result

바뀐 코드

 

그 후 html로 들어가 4번째 순서에 있는 img를 맞게 불러와준다.

                                <div class="product__item">
                                    <div class="product__item__pic set-bg">
                                        <div class="label new">New</div>
                                        <ul class="product__hover">
                                        <!-- 추가 -->
                                        <div><img src="{{baseUrl}}/upload/{{i.3}}" width='500'></div>
                                        <!-- 추가 -->
                                            <li><a href="{{baseUrl}}/upload/{{i.3}}" class="image-popup"><span class="arrow_expand"></span></a></li>
                                            <li><a href="product_details?product_id={{i.0}}"><span class="icon_heart_alt"></span></a></li>
                                            <li><a href="product_details?product_id={{i.0}}"><span class="icon_bag_alt" ></span></a></li>
                                        </ul>
                                    </div>

사진이 잘 나온다.

 

9. 상세보기 페이지에서 이미지 링크 수정

위처럼 모델에 이미지를 추가해주어야한다.

def getProduct_details(product_id):
    conn = ora.connect(database)
    cursor = conn.cursor()
    sql = "select product_name, product_info, sell_price, img from product_info where product_id=:product_id"
    cursor.execute(sql, product_id=product_id)
    result = cursor.fetchone()
    print(result)
    cursor.close()
    conn.close()
    return result

spring 기준으로 만들었던 이미지 링크를 경로에 맞게 수정해준다.

<img alt="상세보기" src="resources/upload/{{res.0}}" width='80%'>

△원래 코드

<img alt="상세보기" src="{{baseUrl}}/upload/{{res.3}}" width='80%'>

바뀐 코드

 

결과

반응형
LIST
반응형
SMALL

리눅스에서 jupyter notebook를 실행하고 윈도우에 설치된 오라클 11g와 연동하는 것까지 해보았다.

 

▼저번 포스팅에서 해본 파이썬 - 오라클 연동 정리(링크)

더보기

방법을 간단히 요약하자면,

 

1) 오라클 connection 연결

2) connection이 cursor 객체 가져옴(연결도구)

3) cursor 객체의 fetch메서드를 이용해서 데이터를 서버로부터 가져온다.

4) cursor 객체의  execute() 메서드를 사용해서 파이썬에 입력한 SQL 문장을 오라클 DB 서버로 보낸다.

5) 주고받는 것이 완료되면 connection 객체의 commit() 메서드를 사용해서 데이터를 확정한다.

6) connection.close()를 해서 오라클과 연결을 끊는다.

 

즉, 정리하자면

오라클 수입 : import cx_Oracle as ora
오라클 Connection 연결 : conn = ora.connect('kosmorpa/test00@192.168.0.122:1522/orcl')
Cursor 불러오기 :  cursor = conn.cursor()
a) SQL 입력문장 -> 오라클 DB : cursor.execute( 전송할 sql 문장 )
b) 오라클 DB 데이터 -> 파이썬 : cursor.fetch*****()
Cursor 닫기 : cursor.close()
오라클 DB 저장 : conn.commit()
오라클 연결 끊기 : conn.close()

이걸 이용해서 파이참(PyCharm)에서 DB를 원래 했던 sqlite가 아닌 윈도우에 설치 되어있는 오라클과 연동해서 해보도록 하자.


 

준비된 템플릿에 회원가입 창과 아이디 중복 확인 프로그램을 만들었었다.

 

이번엔 로그인 앱을 만들어 web1과 연결해보자.

 

## web1에 있는 static 파일을 이용해서 추후 web1에 템플릿 디자인으로 적용해보기.

 


[ login/logout 웹 페이지 기능 구현하기 ]


1. login 앱 만들기

늘 하던대로 login > templates > login > index.html 파일 생성

python manage.py startapp login

 

2. index.html 파일 만들기

회원가입(앞선 포스팅 web1에서 만들었던 tripmember를 링크)과 로그인 폼에는 링크를 걸어두었다.

서버 구동을 확인한 후 로그인 폼(loginform)을 만들러 갈 예정.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index.html</title>
    <style>
        ol, ul {list-style:none;}
        ul li { float:left; margin-left:2px; background:pink}
    </style>
</head>
<body>
    <h1>로그인/로그아웃 데모</h1>
    <span>추후 web1에 템플릿 디자인으로 적용하세요.</span>
<nav id="menu">
    <header class="major">
        <ul>
            <li><a href="main">Home</a> </li>
            <li><a href="survey">설문조사</a> </li>
            <li>김길동님 반갑습니다. </li>
            <li><a href="logout">로그아웃</a> </li>
            <li><a href="/web1/tripmember">회원가입</a> </li>
            <li><a href="loginform">로그인폼</a> </li>
        </ul>
    </header>
</nav>
</body>
</html>

3. 뷰 추가(view.py)

이제 이쯤이야 쉽다. 첫페이지 추가

4. urls.py 만들고 내용 추가

5. config/setting 추가

6. config/urls 추가

7. 서버 구동 및 index.html 파일 열기

대충 이런모양이다.

기본 세팅 끝.


본격적으로 첫 페이지의 로그인 폼을 만들러 가자.


 

8. login.html 만들기

index에 web1에서 썼었던 로그인폼 그대로 가져와서 내용 추가하자.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login.html</title>
    <style>
        ol, ul {list-style:none;}
        ul li { float:left; margin-left:2px; background:pink}
    </style>
</head>
<body>
    <h1>로그인 페이지</h1>
    <span>추후 web1에 템플릿 디자인으로 적용하세요.</span>
<nav id="menu">
    <section id="main">
        <header>
            <h2>StarTrip</h2>
            <form method="post" action="">
                {% csrf_token %}
                <div class="fields">
                    <div class="field">
                        <input type="text" name="id" id="id" value="" placeholder="ID"
                        style="text-transform :lowercase"/>
                    </div>
                    <div class="field">
                        <input type="password" name="pwd" id="pwd" placeholder="Password" />
                    </div>
                </div>
                <ul class="actions special">
                    <li><input type="submit" value="로그인" class="primary"/></li>
                </ul>
                <div><span style="color:red;">{{error}}</span> </div>
            </form>
        </header>
    </section>
</nav>
</body>
</html>

 

9. views.py로 와서 추가

login.html를 loginform 이름으로 정의하자.

여기서는 if문을 사용해서 loginform에 대해 1) 전송방식 구분 2) Session 유무에 따른 구분 을 두자.

 

▼왜 갑자기 세션이 나와?

더보기

갑자기 세션이 등장했다.(두둥탁)

JSP에서 쓰던 Session에 대한 개념을 여기에 정리해보고자 한다.

 

원래 HTTP는 비연결성 프로토콜(stateless)이기 때문에 전단계의 데이터 요청과 다음 데이터 요청이 관련이 없다. 이렇게 되면 항상 새롭게 매번, 데이터를 요청하고 받아와야 하기 때문에, 세션과 쿠키가 등장했다. 세션은 웹 컨테이너, 쿠키는 웹 브라우저에 상태 유지를 위한 정보를 저장한다.

 

예시를 들어보자.

원래 회원가입 절차는 사용자가 무조건 각 단계를 순차적으로 넘어와야 한다. HTTP로 구현을 하게 되면 모든 페이지에 대해서 URL(/step1/, /step2/, /step3/)로 접근할 수 있다. 하지만 세션을 사용하면 각 정보를 저장하기 때문에 /step1/ => /step2/ => /step3/ 순서로만 접근이 가능하게 바꿀 수 있다. 각 단계의 순서대로 접근하지 않으면 403 Forbidden 페이지를 볼 수 있을 것이다.

 

Django에서는 기본적으로 세션 관리 기능을 제공해주고, request.session 이라는 딕셔너리 객체에 필요한 값을 저장하고 읽어올 수 있다. view.py 에서 return을 걸어주기 전에 if문을 통해 step1에서 step2로만 가게끔(나머지는 false가 되게끔) 만들면 접근 순서를 제어할 수 있다. (출처)


▽코드 문장으로 읽기

더보기

loginform 두가지 if문이 중첩되어 있다.

1) 만약 user_id 가 request.session(=딕셔너리 객체에 필요한 값을 저장하고 읽어옴) 안에 있다면 /login 페이지로 이동해라.

2) 만약 요청방법이(로그인 폼에서 submit 버튼 누르고 id 비번 값이 넘어가는는 방법이) POST이면?

   n -> login/login.html로 가라.

   y -> post 방식으로 id를 요청해서 user_id 안에 넣어라.(비밀번호도) 그 후에 print해라.

   (db_id와 db_pwd 는 아직 db 연동을 하지 않았기 때문에 임의로 정해놓았음)

   2-1) 그 후 또다른 if문

      만약 db 안에 user 의 아이디와 비밀번호가 있다면? y -> 로그인 성공 띄우고 /login으로 가라.

      n -> 로그인 실패 띄우고 에러메시지 띄우고,  login/login.html로 가라.


from django.shortcuts import render, redirect

# Create your views here.
from django.views.decorators.csrf import csrf_protect


def home(request):
    return render(request, "login/index.html")


# 1. 전송방식 구분
# 2. Session 유무에 따른 구분
@csrf_protect
def ldginform(request):
    # 세션에 등록한 값이 존재하는가?
    if 'user_id' in request.session:
        return redirect('/login')

    if request.method == 'POST':
        user_id = request.POST['id']
        user_pwd = request.POST['pwd']
        print('user_id: ', user_id)
        print('user_pwd: ', user_pwd)
        db_id = 'xman'
        db_pwd = '11'
   
   # 중첩 if 문   
        if user_id in db_id and user_pwd in db_pwd:
            print('로그인 성공')
            request.session['user_id'] = db_id
            request.session['user_name'] = '김길동'
            return redirect('/login')
        else:
            print('로그인 실패')
            msg = '아이디나 비밀번호가 잘못되었습니다.'
            return render(request,"login/login.html",{"error":msg})
    return render(request, "login/login.html")

10. 로그아웃도 추가(view.py)

세션을 삭제하고 나간다.

# 로그아웃 처리
def logout(request):
    del request.session['user_id']
    del request.session['user_name']
    return redirect('/login')

당연히 view에 정의했으니 길 터줘야 한다.

11. urls.py에 path 추가

간-단

12. 세션 나눠주기(index.html)

views.py에서 if문으로 상황에 따라 경로를 만들어주었다.

첫 페이지인 index.html에서도 각 부분에 따른 세션을 나눠줘야 한다. 각각 if / else를 나눠 표시해주자.

왜??

        <ul>
            <li><a href="main">Home</a> </li>
            <li><a href="survey">설문조사</a> </li>

            {% if 'user_id' in request.session %}
            <li>{{request.session.user_name}}님 반갑습니다. </li>
            <li><a href="logout">로그아웃</a> </li>
            {% else %}
            <li><a href="/web1/tripmember">회원가입</a> </li>
            <li><a href="loginform">로그인폼</a> </li>
            {% endif %}
        </ul>

 

[ 실습 예제 ]

[ cx_oracle과 연동해서 로그인 프로그램 완성하기 ]

def getLoginChk() 함수를 만들어서 인자 정의 및 구현을 한다.

 

13. 로그인을 체크하는 모델 추가(models.py)

오라클과 연결하고 sql문을 전송 및 값을 받아온다. datas의 경우 fetchall()로 모든 결과를 리턴한다.

[ Fatch 종류 ]

fetchall()의 경우 결과를 모두 리턴
fetchone()의 경우 하나의 row를 리턴
fetchmany(num rows)의 경우 rows의 숫자 만큼 리턴을 한다.

 

from django.db import models
import cx_Oracle as ora

database = 'kosmorpa/test00@192.168.0.122:1522/orcl'
# Create your models here.

# select count(*) cnt, name from member_table where id='xman' and pwd='121'
# 인자값이 여러개일 경우 함수의 인자를 늘여서 사용하게 되는 부분을 리팩토링한다.
def getLoginChk(**kwargs):
    conn = ora.connect(database)
    cursor = conn.cursor()
    sql_select = "select count(*) cnt, name from member_table" \
                 " where id=:id and pwd=:pwd group by name"
    cursor.execute(sql_select, id=kwargs['id'], pwd=kwargs['pwd'])
    datas = cursor.fetchall()
    cursor.close()
    conn.close()
    return datas

 

 

▼kwargs와 args

더보기

kwargs와 args는 파이썬에서 기존의 함수에 파라미터를 추가하여 새로운 함수를 만드는 경우에 사용한다.

별표시(***)의 경우, 여러 개의 인수를 받을 때, 키워드 인수를 받을 때 사용하는 표시이다.

 

1) **kwargs (keyword argument)

 

**kwargs는 {'키워드': '특정 값'} 형태로 함수를 호출할 수 있다. 또는 특정 키워드에 반응하여 함수를 작성하는 방법도 있다.(if문 사용) 단, 신규로 추가할 파라미터를 **kwargs 의 왼쪽에 써야 한다.

ex)def a(**kwargs, a): 은 틀린 문법(SyntaxError)

 

2) *args(argument)

 

*args 여러개의 인자를 함수로 받고자 할 때 쓰인다. 이름은 임시로 지은거라 *a , *banana 등등 다 가능하다. 튜플(tuple) 형태로 여러개의 인자를 함수로 출력하게 될 경우 {'a', 'b', 'c' } 와 같이 튜플 형태로 출력된다.

 

(예시 출처)

 

1. hello( ) 함수가 있습니다. 부서명과 이름을 받아 인사합니다.

 

2. 어느날 여러 번 인사와 함께 just do it! 을 외치는 새로운 함수를 만들어야 합니다.

단순히 아래처럼 같은 내용을 또 선언 할 수도 있습니다.

)

런 경우 hello( ) 내용이 달라지면 hello_repeat도 변경해야하는 번거로움이 있습니다.

 

3. 이런 경우 기존 hello( )를 그대로 사용하면서 파라미터만 추가로 선언하는 방법을 사용할 수 있습니다.

결과가 같습니다. 이제 hello( ) 내용이 변경되더라도 hello_repeat( )는 변경할 필요가 없습니다.

kwargs와 args는 파이썬에서 기존의 함수에 파라미터를 추가하여 새로운 함수를 만드는 경우에 사용한다.

별표시(***)의 경우, 여러 개의 인수를 받을 때, 키워드 인수를 받을 때 사용하는 표시이다.

 

1) **kwargs (keyword argument)

 

**kwargs는 {'키워드': '특정 값'} 형태로 함수를 호출할 수 있다. 또는 특정 키워드에 반응하여 함수를 작성하는 방법도 있다.(if문 사용) 단, 신규로 추가할 파라미터를 **kwargs 의 왼쪽에 써야 한다.

ex)def a(**kwargs, a): 은 틀린 문법(SyntaxError)

 

2) *args(argument)

 

*args 여러개의 인자를 함수로 받고자 할 때 쓰인다. 이름은 임시로 지은거라 *a , *banana 등등 다 가능하다. 튜플(tuple) 형태로 여러개의 인자를 함수로 출력하게 될 경우 {'a', 'b', 'c' } 와 같이 튜플 형태로 출력된다.

 


(예시 출처)

 

1. hello( ) 함수가 있습니다. 부서명과 이름을 받아 인사합니다.

def hello(department, name):
    print('hello ' + department + ' team ' + name)

 

2. 어느날 여러 번 인사와 함께 just do it! 을 외치는 새로운 함수를 만들어야 합니다.

단순히 아래처럼 같은 내용을 또 선언 할 수도 있습니다.

def hello_repeat(num, department, name):
    for i in range(num):
        print('hello ' + department + ' team ' + name)
    print('just do it!')

)

런 경우 hello( ) 내용이 달라지면 hello_repeat도 변경해야하는 번거로움이 있습니다.

 

3. 이런 경우 기존 hello( )를 그대로 사용하면서 파라미터만 추가로 선언하는 방법을 사용할 수 있습니다.

def hello_repeat(num, **kwargs):
    for i in range(num):
        hello(**kwargs)
    print('just do it!')

결과가 같습니다. 이제 hello( ) 내용이 변경되더라도 hello_repeat( )는 변경할 필요가 없습니다.


 

 

15. views 가서 바꾸기

DB를 연결했으므로 임의로 정한 db_id, db_pwd가 아닌 오라클 DB에 있는 id와 pwd인지 if문을 이용해서 결과값을 리턴한다. 세션에 저장된 user_id가 id와 같을 경우, 로그인 성공창과 함께 0행 1열(2차원 배열 : 즉, 1행2열)을 이름값으로 가져온다.로그인이 실패되면 msg를 띄운다.

@csrf_protect
def loginform(request):
    # 세션에 등록한 값이 존재하는가?
    if 'user_id' in request.session:
        return redirect('/login')

    if request.method == 'POST':
        user_id = request.POST['id']
        user_pwd = request.POST['pwd']
        print('user_id: ', user_id)
        print('user_pwd: ', user_pwd)

        # ----------------- 리펙토링한거 ------------------
        res = getLoginChk(id=user_id,pwd=user_pwd)
        print('='*30)
        print(res)
        if len(res) > 0:
            print('로그인 성공')
            request.session['user_id'] = user_id
            request.session['user_name'] = res[0][1]
            return redirect('/login')
        else:
            print('로그인 실패')
            msg = '아이디나 비밀번호가 잘못되었습니다.'
            return render(request, "login/login.html", {"error": msg})

    return render(request, "login/login.html")

 

좌 : 기존 우 : 바꾼거

DB와 연동되어 로그인이 잘 되었다.

 

로그인 성공
로그인에 실패했을 경우

▼ 전체 코드 보기

더보기

[전체 코드]

1. index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index.html</title>
    <style>
        ol, ul {list-style:none;}
        ul li { float:left; margin-left:2px; background:pink}
    </style>
</head>
<body>
    <h1>로그인/로그아웃 데모</h1>
    <span>추후 web1에 템플릿 디자인으로 적용하세요.</span>
<nav id="menu">
    <header class="major">
        <ul>
            <li><a href="main">Home</a> </li>
            <li><a href="survey">설문조사</a> </li>

            {% if 'user_id' in request.session %}
            <li>{{request.session.user_name}}님 반갑습니다. </li>
            <li><a href="logout">로그아웃</a> </li>
            {% else %}
            <li><a href="/web1/tripmember">회원가입</a> </li>
            <li><a href="loginform">로그인폼</a> </li>
            {% endif %}
        </ul>
    </header>
</nav>
</body>
</html>

2. login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login.html</title>
    <style>
        ol, ul {list-style:none;}
        ul li { float:left; margin-left:2px; background:pink}
    </style>
</head>
<body>
    <h1>로그인 페이지</h1>
    <span>추후 web1에 템플릿 디자인으로 적용하세요.</span>
<nav id="menu">
    <section id="main">
        <header>
            <h2>StarTrip</h2>
            <form method="post" action="">
                {% csrf_token %}
                <div class="fields">
                    <div class="field">
                        <input type="text" name="id" id="id" value="" placeholder="ID"
                        style="text-transform :lowercase"/>
                    </div>
                    <div class="field">
                        <input type="password" name="pwd" id="pwd" placeholder="Password" />
                    </div>
                </div>
                <ul class="actions special">
                    <li><input type="submit" value="로그인" class="primary"/></li>
                </ul>
                <div><span style="color:red;">{{error}}</span> </div>
            </form>
        </header>
    </section>
</nav>
</body>
</html>

3. models.py

from django.db import models
import cx_Oracle as ora

database = 'kosmorpa/test00@192.168.0.122:1522/orcl'
# Create your models here.

# select count(*) cnt, name from member_table where id='xman' and pwd='121'
# 인자값이 여러개일 경우 함수의 인자를 늘여서 사용하게 되는 부분을 리팩토링한다.
def getLoginChk(**kwargs):
    conn = ora.connect(database)
    cursor = conn.cursor()
    sql_select = "select count(*) cnt, name from member_table" \
                 " where id=:id and pwd=:pwd group by name"
    cursor.execute(sql_select, id=kwargs['id'], pwd=kwargs['pwd'])
    datas = cursor.fetchall()
    cursor.close()
    conn.close()
    return datas

4. urls.py

from django.urls import path

from login import views

urlpatterns=[
    path('',views.home),
    path('loginform',views.loginform),
    path('logout',views.logout),
]

5. views.py

from django.shortcuts import render, redirect
from .models import *

# Create your views here.
from django.views.decorators.csrf import csrf_protect


def home(request):
    return render(request, "login/index.html")


# 1. 전송방식 구분
# 2. Session 유무에 따른 구분
@csrf_protect
def loginform(request):
    # 세션에 등록한 값이 존재하는가?
    if 'user_id' in request.session:
        return redirect('/login')

    if request.method == 'POST':
        user_id = request.POST['id']
        user_pwd = request.POST['pwd']
        print('user_id: ', user_id)
        print('user_pwd: ', user_pwd)

        # ----------------- 리펙토링한거 ------------------
        res = getLoginChk(id=user_id,pwd=user_pwd)
        print('='*30)
        print(res)
        if len(res) > 0:
            print('로그인 성공')
            request.session['user_id'] = user_id
            request.session['user_name'] = res[0][1]
            return redirect('/login')
        else:
            print('로그인 실패')
            msg = '아이디나 비밀번호가 잘못되었습니다.'
            return render(request, "login/login.html", {"error": msg})

    return render(request, "login/login.html")


# from .models import * 위쪽에 해줘야함

# ---------------------기존 코드 -> 리펙토링 해보기 ------------------------------
 #       db_id = 'xman'
 #       db_pwd = '11'
 #       if user_id in db_id and user_pwd in db_pwd:
 #           print('로그인 성공')
 #           request.session['user_id'] = db_id
 #           request.session['user_name'] = '김길동'
  #          return redirect('/login')
 #       else:
  #          print('로그인 실패')
   #         msg = '아이디나 비밀번호가 잘못되었습니다.'
   #         return render(request,"login/login.html",{"error":msg})
   # return render(request, "login/login.html")
# ------------------------------------------------------------------------------


# 로그아웃 처리
def logout(request):
    del request.session['user_id']
    del request.session['user_name']
    return redirect('/login')

 

cf) 웹브라우저에 SessionId가 쿠키에 저장되어있는지 확인하는 방법

 

반응형
LIST
반응형
SMALL

1. 오라클 워크시트에 테이블과 시퀀스 생성하기

create table board(
no number CONSTRAINT board_no_pk primary key,
pwd varchar2(10),
writer varchar2(34),
subject varchar2(100),
content varchar2(400),
regdate date default sysdate
);

create sequence board_seq
increment by 1
start with 1;

저장하고 실행.

 

2. 리눅스 터미널에서 jupyter-notebook 실행

(아나콘다가 깔려있어야 한다.)

base에서 실행한다.

3. workspace 역할을 할 디렉토리 만들자.

new > folder > 파이썬 파일 하나 만들기

그리웠다 주피터..... 필기 자유로운게 너무 좋다ㅠ

 

4. 오라클 연동 후 필수 라이브러리 설치
!pip install cx_Oracle 설치하기

!pip install cx_Oracle

다운로드 되거나,  이미 설치되어 있으면 이미 했다고 뜸

 

 

5. 오라클 연결

#오라클 수입
import cx_Oracle as ora

현재 주피터와 오라클 데이터베이스를 연결하는 클래스이다.

앞으로 계속 껐다가 킬껀데, 그때마다 다시 켜주는 장치다. 

#오라클 connection 연결
conn = ora.connect('kosmorpa/test00@192.168.0.122:1522/orcl')
print(conn.version)

나는 버전이 11.2.0.1.0이다. 저번 포스팅에서 깔았던 그 오라클 버전.

print(conn)

잘 연결되었다.

이러면 윈도우에서 오라클 DB가 있어도 리눅스에서 작업할 수 있어서 훨씬 편하다.

 

6. 커서 변환하기

conn.cursor : 연결된 데이터 베이스에 sql 문장을 실행하고 데이터를 가져오는 역할

#커서 변환하기
cursor = conn.cursor()
print(cursor)

 

▼ connection 클래스와 cursor 클래스

더보기

[ Connection클래스 ]

연결된 데이터베이스를 동작시키는 역할을 한다.

>Connection.cursor()

Cursor객체를 생성한다.

 

>Connection.commit()

현재 트랜잭션의 변경내역을 DB에 반영(commit)한다.

이 메서드를 명시적으로 호출하지 않으면 작업한 내용이 DB에 반영되지 않으므로, 다른 연결(Connection)에 그 내용이 나타나지 않는다.

 

>Connection.rollback()

가장 최근의 commit()이후 지금까지 작업한 내용에 대해서 DB에 반영하지 않고, 트랜잭션 이전 상태로 되돌린다.

 

>Connection.close()

DB연결을 종료한다.

자동으로 commit()메서드를 호출하는것이 아니기에, close()메서드를 호출하기 이전에 commit()/rollback()중 하나를 명시적으로 호출해야 한다.

 

>Connection.isolation_level

트랜잭션의 격리수준(isolation level)을 확인/설정한다.

입력가능한 값은 None, DEFERRED, IMMEDIATE, EXCLUSIVE이다.

 

>Connection.execute(sql[, parameters])

>Connection.executemany(sql[, parameters])

>Connection.executescript(sql_script)

임시 Cursor객체를 생성하여 해당 execute계열메서드를 수행한다

(Cursor클래스의 해당 메서드와 동일하므로 Cursor클래스에서 설명하겠다.)

 

>Connection.create_aggregate(name, num_params, aggregate_class)

사용자정의 집계(aggregate)함수를 생성한다.

 

>Connection.create_collation(name, callable)

문자열 정렬시 SQL구문에서 사용될 이름(name)과 정렬 함수를 지정한다.

정렬함수는 인자로 문자열 2개를 받으며, 첫 문자열이 두번째 문자열보다 순서가 낮은경우 -1, 같은경우 0, 높은경우 1을 반환해야 한다.

 

>Connection.iterdump()

연결된 DB의 내용을 SQL질의 형태로 출력할수 있는 이터레이터를 반환

 

 

[ Cursor클래스 ]

실질적으로 데이터베이스에 SQL문장을 수행하고, 조회된 결과를 가지고 오는 역할을 한다.

>Cursor.execute(sql[, parameters])

SQL문장을 실행한다. 실행할 문장은 인자를 가질수 있다.

 

>Cursor.executemany(sql, seq_of_parameters)

동일한 SQL문장을 파라미터만 변경하며 수행한다.

파라미터 변경은 파라미터 시퀸스, 이터레이터를 이용할수 있다.

 

>Curosr.executescript(sql_script)

세미콜론으로 구분된 연속된 SQL문장을 수행한다.

 

>Cursor.fetchone()

조회된 결과(Record Set)로부터 데이터 1개를 반환한다. 더 이상 데이터가 없는 경우 None을 반환한다.

 

>Cursor.fetchmany([size=cursor.arraysize])

조회된 결과로부터 입력받은 size만큼의 데이터를 리스트 형태로 반환한다.

데이터가 없는 경우 빈 리스트를 반환한다.

 

>Cursor.fetchall()

조회된 결과 모두를 리스트형태로 반환한다.

데이터가 없는 경우, 빈리스트를 반환한다.

 

출처 : m.blog.naver.com/dudwo567890/130165627205

 

연결은 끝났고 다양하게 오라클과 연동해보자.


[연동 방식]

  1. DB 접속이 성공하면, Connection 객체로부터 cursor() 메서드를 호출하여 Cursor 객체를 가져온다. DB 커서는 Fetch 동작을 관리하는데 사용되는데, 만약 DB 자체가 커서를 지원하지 않으면, Python DB API에서 이 커서 동작을 Emulation 하게 된다.
  2. Cursor 객체의 execute() 메서드를 사용하여 SQL 문장을 DB 서버에 보낸다.
  3. SQL 쿼리의 경우 Cursor 객체의 fetchall(), fetchone(), fetchmany() 등의 메서드를 사용하여 데이타를 서버로부터 가져온 후, Fetch 된 데이타를 사용한다.
  4. 삽입, 갱신, 삭제 등의 DML(Data Manipulation Language) 문장을 실행하는 경우, INSERT/UPDATE/DELETE 후 Connection 객체의 commit() 메서드를 사용하여 데이타를 확정 갱신한다.
  5. Connection 객체의 close() 메서드를 사용하여 DB 연결을 닫는다.

▼한국인을 위한 요약

더보기

방법을 간단히 요약하자면,

 

1) 오라클 connection 연결

2) connection이 cursor 객체 가져옴(연결도구)

3) cursor 객체의 fetch메서드를 이용해서 데이터를 서버로부터 가져온다.

4) cursor 객체의  execute() 메서드를 사용해서 파이썬에 입력한 SQL 문장을 오라클 DB 서버로 보낸다.

5) 주고받는 것이 완료되면 connection 객체의 commit() 메서드를 사용해서 데이터를 확정한다.

6) connection.close()를 해서 오라클과 연결을 끊는다.

 

즉, 정리하자면

오라클 수입 : import cx_Oracle as ora
오라클 Connection 연결 : conn = ora.connect('kosmorpa/test00@192.168.0.122:1522/orcl')
Cursor 불러오기 :  cursor = conn.cursor()
a) SQL 입력문장 -> 오라클 DB : cursor.execute( 전송할 sql 문장 )
b) 오라클 DB 데이터 -> 파이썬 : cursor.fetch*****()
Cursor 닫기 : cursor.close()
오라클 DB 저장 : conn.commit()
오라클 연결 끊기 : conn.close()

이걸 이용해서 파이참(PyCharm)에서 DB를 원래 했던 sqlite가 아닌 윈도우에 설치 되어있는 오라클과 연동해서 해보도록 하자.



 

 

1. 입력처리

 

1) 디장고에서 폼으로 작성할 것

#디장고에서 폼으로 작성할 것
writev = input('작성자 : ')
pwdv = input('비밀번호 : ')
subjectv = input('제목 : ')
contentv= input('내용 : ')

2) 입력해주고 insert 하는 sql문을 실행해준다.

#SQL문 작성
sql_insert ='insert into board values(board_seq.nextVal,:pwd,:write,:subject,:content,sysdate)'
sql_insert
#입력값을 쿼리에 바인딩한 후 전송
cursor.execute(sql_insert,pwd=pwdv,write=writev,subject=subjectv,content=contentv)
#커서 닫고 commit 해준다.
cursor.close()
conn.commit()

전부 dd로 입력 후 저장

3) 오라클에 데이터가 잘 들어간 것을 볼 수 있다.

4) 오라클과 연결을 종료할 때. 하지만 지금은 닫지 않는다.

#오라클과 연결 종료
conn.close()

 

 

2. 출력

1) 변수 지정

sql_select = 'select no,writer,subject,regdate from board order by 1 desc'
cursor.execute(sql_select)

Cursor 객체의 execute() 메서드를 사용하여 SQL 문장을 DB 서버에 전송

 

2) 데이터를 서버로부터 가져온다.

print(cursor.fetchall())

 

3) 출력 완료 후 닫는다.

cursor.close()
conn.close()

 

3. 상세보기 구현

 

번호를 입력받아서 사용자의 정보를 모두 출력해보자.
fetchone() 사용해서 적용하기

#findone() : mybastis select_one()
nov = input("상세보기 값 : ")
sql_no = "select no,writer,subject,content,\
to_char(regdate,'yyyy-mm-dd') regdate from board where no=:no"
cursor = conn.cursor()
print(cursor)
cursor.execute(sql_no,no=nov)
print(cursor.fetchone())

 

4. 최근 글 5개만 출력하기(select)

#함수로 정의
def connections():
    try:
        conn= ora.connect('kosmorpa/test00@192.168.0.122:1522/orcl')
        cursor = conn.cursor()
    except Exception as e:
        msg="예외발생"
        print(msg)
    return conn
#최근 글 5개만 출력 fetchmany
def myFetchmany():
    conn  = connections()
    cursor = conn.cursor()
    sql_select = 'select * from board order by 1 desc'
    cursor.execute(sql_select)
    numRows = 5
    res = cursor.fetchmany(numRows = numRows)
    print('fetchmany {}'.format(numRows))
    cursor.close()
    conn.close()
    return res
print(myFetchmany())

 

cf ) 서브쿼리를 이용해서 동일한 결과를 가져올 수 있다.(rowNum)

# 서브쿼리 사용해서 최근 5개만 추출해보기(위에 fetchmany와 동일하다.)
def examSelect():
    conn  = connections()
    sql_select = "select no,writer,content,regdate from\
    (select rownum,no,writer,content,regdate from\
    (select * from board order by 1 desc) where rownum <=5)"
    cursor = conn.cursor()
    cursor.execute(sql_select)
    rs = cursor.fetchall()
    return rs
selectList = examSelect()
selectList

 

 

5. 삭제

#삭제 - insert, delete ,update
def boardDel(num):
    conn  = connections()
    cursor = conn.cursor()
    sql_delete = 'delete from board where no = :no'
    try:
        cursor.execute(sql_delete, no=num)
        conn.commit()
    except Exeption as e:
        print(e)
    finally:
        conn.close()

num = input('삭제번호 :')
boardDel(num)
examSelect()

10번이 사라졌다.

 

 

 


1. 카페에서 파일 다운로드(리눅스에서 다운받기)

 

2. 파이참에서 web1 이라는 앱 만들기

python manage.py startapp web1

3. templates>web1 > 파일 폴더 만들기

 

4. 다운받은 파일 홈 디렉토리로 옮겨버리고 압축을 풀자

mv base.html ~
mv static.zip ~
cd ~
unzip static.zip

압축도 풀어줌

5. 홈에 푼 파일들을 다시 우리 프로젝트 환경에 templates에 옮겨줘야한다.

mv base.html PycharmProjects/myapps/web1/templates/web1/

static 안에는 assets라는 폴더가 들어있다. 다시 web1에 리소스 파일을 넣을 static에 넣어준 후 옮겨준다.

mv assets/ PycharmProjects/myapps/web1/templates/web1/static/

 

 

6. urls에 홈 경로, views에 렌더링 입력, config/setting 에 web1 등록, config/urls에 등록.

참 쉽죠?

아직 DB를 안 건드렸으니까 admin과 마이그레이션은 안한다.

 

실행해보면,

python manage.py runserver

따란!

static에 모든 css와 js가 다 있어서 편했다.

 

7. sql에 member_table 테이블 생성하기

create table member_table(
num number constraint member_table_num_pk primary key,
id varchar2(15) constraint member_table_id_nn not null,
pwd varchar2(15) constraint member_table_pwd_nn not null,
name varchar2(34),
tel varchar2(54),
emain varchar2(54),
addr varchar2(100),
npoint number(5),
rdate date,
constraint member_table_id_uq unique(id));

create sequence member_table_seq
increment by 1
start with 1;

 

8. 이제 회원가입 페이지를 만들거다.

base.html의 내용을 복사해서 tripmember.html 만들기

content 부분 변경하기 -> 회원가입 폼으로 변경할 것.

카페에 올라온 거 붙여넣고

				<!-- Banner -->
				<section id="banner">
					<div class="content">
						<!---- content 시작! -->
						<form method="post" action="tripinsert">
							{% csrf_token %}
							<div class="row gtr-uniform">
								<!-- 카페 코드 추가(회원가입창 만들기) -->
								<div class="col-6 col-12-xsmall">
									<input type="text" name="id" id="id" value="" placeholder="ID" />
								</div>
								<div class="col-6 col-12-xsmall">
									<input type="password" name="pwd" id="pwd" value="" placeholder="비밀번호" />
								</div>
								<div class="col-6 col-12-xsmall">
									<input type="password" name="chkpwd" id="chkpwd" value="" placeholder="비밀번호 확인" />
								</div>
								<div class="col-6 col-12-xsmall">
									<input type="text" name="name" id="name" value="" placeholder="이름" />
								</div>
								<div class="col-6 col-12-xsmall">
									<input type="tel" name="tel" id="tel" value="" placeholder="전화번호" />
								</div>
								<div class="col-6 col-12-xsmall">
									<input type="email" name="email" id="email" value="" placeholder="Email" />
								</div>
								<div class="col-6 col-12-xsmall">
									<input type="text" name="addr" id="addr" value="" placeholder="주소" />
								</div>
								<!-- Break -->
								​
								<div class="col-12">
									<ul class="actions">
										<li><input type="submit" value="가입하기" class="primary" /></li>
										<li><input type="reset" value="취소하기" /></li>
									</ul>
								</div>
								<!--  회원가입창 끝 -->
							</div>
						</form>
						<!-- content 끝! -->
					</div>
					<span class="image object">
						<img src="{{baseUrl}}/assets/img/main.jpg" alt="" />
					</span>
				</section>
				<!-- Banner 섹션 끝-->
                <!-- Section 지움-->

urls.py에 추가하기

views 추가

 

섹션부분 전부 지우기(깔끔하게)

 

 

9. models 가자.

오라클로 연결하면 자동으로 마이그레이션이 생기지 않는다. 따라서 아까 주피터에서 했던 것 처럼 데이터를 불러오자.

 

여기는 base가 아니라 myapp이기 때문에 cx_Oracle를 다시 받아줘야한다. 잠시 서버 멈추고 다운 받고 해보자

pip install cx_Oracle

 

 

10. 아까 주피터에서 했던 것처럼 가져오자.

모델에 작성하기

예외있으면 예외발생 메시지 나오게 하자.

from django.db import models
import cx_Oracle as ora
# Create your models here.

def connections():
    try:
        conn= ora.connect('kosmorpa/test00@192.168.0.122:1522/orcl')
    except Exception as e:
        msg="예외발생"
        print(msg)
    return conn

def memberinsert(addr_list):
    print(addr_list)
    conn=connections()
    cursor=conn.cursor()
    sql="insert into member_table values(member_table_seq.nextVal,:1,:2,:3,:4,:5,:6,0,sysdate)"
    cursor.execute(sql,addr_list)
    cursor.close()
    conn.commit()
    conn.close()

11. view 수정

from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_protect

from web1.models import memberinsert


def home(request):
    return render(request, "web1/base.html")

def tripmember(request):
    return render(request, "web1/tripmember.html")

@csrf_protect
def tripinsert(request):
    #print(request.POST['id'])
    members = (request.POST['id'], 
               request.POST['pwd'], 
               request.POST['name'], 
               request.POST['email'],  
               request.POST['tel'],  
               request.POST['addr']
               )
    memberinsert(members)
    return redirect('/web1/')

12. 회원가입 창에 아이디 중복 체크 만들기

버튼은 따로 만들어주심

<div class="col12">
	<ul class="actions">
		<li>
			<input type="text" name="id" id="id" value="" placeholder="ID"/>
		</li>
		<li>
			<input type="button" id="idchk" value="중복체크"/>
		</li>
		<li>
		<span id="target" class="col-6 col-12-xsmall">ㅇㅇ</span>
		</li>
	</ul>
</div>

이걸 아까 있던 id 자리에 바꿔넣는다.

 

반응형
LIST
반응형
SMALL

쉽게 분석 결과를 시각화해서 첨부할 수 있다.

바로 여기!

링크 : c3js.org/examples.html

 

C3.js | D3-based reusable chart library

Number Format Localization Number format localization using D3 locale settings. View details »

c3js.org

 

아래 코드를 복사해서 써보자

바로 전 포스팅에서 만들었던 설문조사 폼에서 시도해보자.

 

설문 결과창에 파이차트를 띄워보려고 한다.

 

 

[연습]

 

1. chart1.html 파일 만들기

 

2. view에 추가

 

3. urls 추가

 

4. 파이 차트 주소를 바디에 붙여넣기

<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>

이렇게 받아오는 걸 제이쿼리(선택자)로, 스크립트로, 제이슨으로도 불러올 수 있다.

 

5. js 파일 붙여넣기

어차피 setTomeout은 필요 없다. 그 앞에까지만 복붙해보자.

스크립트 안 제이쿼리에 붙여넣기.

 

 

컬럼의 차트, 데이터를 컬럼에서 가져와 var로 선언만 해주면 된다.

    
    $(function(){
    
    //여기 붙여넣기
    
    var chart = c3.generate({
    bindto :'#chart_donut',    //이거 쓴거    
    data: {
        columns: [
            ['data1', 30],
            ['data2', 120],
            ['data3', 150],
        ],
        type : 'pie',
    }
});
    

이거를

    $(function(){
    
    //여기 붙여넣기
    var chartData = [
            ['data1', 30],
            ['data2', 120],
            ['data3', 150],
        ];
    
    var chart = c3.generate({
    bindto :'#chart_donut',    //이거 쓴거    
    data: {
        columns: chartData,
        type : 'pie',
    }
});

이렇게 추가해주면 데이터가 변할 때 chartData 부분만 수정해 주면 된다.

 

이런식으로 결과값이 나온다.

 

 

[ 설문조사 결과폼에 적용해보기 ]

1. result.html 파일 하단에 <script> 추가하기

링크를 연결하거나 할 필요는 없다. 결과 확인창에 나오는 값을 그대로 데이터로 가져와서 차트의 데이터(chartData) 부분에 넣어주면 된다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>result.html</title>
<style>
        #wrap { border:1px sloid #000; width:450px; margin:auto; }
        table { border-collapse: collapse; width:100% }
        th,td { padding:8px; text-align:left;
        border-bottom: 1px solid #ddd;
        }
        tr:hover { background:#f5f5f5; cursor:pointer }

    </style>

</head>
<body>
<div id="wrap">
    <h1>설문조사 결과보기 예제</h1>
    <table id = "datatable">
        <thead>
            <tr>
                <th>문항</th>
                <th>응답수</th>
            </tr>
        </thead>
        <tbody>
            {% for row, ans in surveyList %}
            <tr>
                <td>{{ans}}</td>
                <td>{{row.sum_num}}</td>
                <!--sql에 있는 테이블 row 가져오기-->
            </tr>
            {%endfor%}
        </tbody>
        <tr>
            <td colspan="2">
                <input type="button" value="투표하기" onclick="location='/survey'">
            </td>
        </tr>
    </table>
</div>

<!--================================================================-->
<!--파이차트 들어갈 곳-->
<div id="chart_donut"></div>

<!--파이차트 연결 주소-->
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>

<!--파이차트 연결 주소 끝-->

<!-- 파이차트 연결하기-->
<script>
  $(function(){

        var chartData=[
        
        ];
       
        var chart = c3.generate({
        bindto:'#chart_donut',
        data: {

        columns: chartData,
        type : 'pie',

    }
});

    });


</script>
<!--================================================================-->
</body>
</html>

 

2. 파이차트의 데이터를 불러오기 위해 값을 넣어준다(input)

hidden으로 숨겨서 들어온다.

sql 테이블에서 가져온 데이터들(ans, row.sum_num) 을 value값으로 지닌 클래스를 설정해준다.

            {% for row, ans in surveyList %}
            <tr>
                <!--=================================================================================-->
                <input type="hidden" class="ans" name="ans" value="{{ans}}">
                <input type="hidden" class="sum_num" name="sum_num" value="{{row.sum_num}}">
                <!--=================================================================================-->

                <td>{{ans}}</td>
                <td>{{row.sum_num}}</td>
                <!--sql에 있는 테이블 row 가져오기-->
            </tr>
            {%endfor%}

위치는 ans와 row.sum_num을 surveyList에서 가져온 디장고 탬플릿 태그(  {% %}  ) 안에 써줘야 한다.

 

3. 데이터를 받아오기 위해 여러 방법으로 받아온다.

답변이 4개이기 때문에 데이터를 여러가지 방법으로 가져올 수 있다.

 

1) 반복문 사용

  $(function(){
        var chartData=[];

        for(var i=0;i<$('.ans').length; i++){
            chartData.push([$('.ans').eq(i).val(),$('.sum_num').eq(i).val()]);
        }
            
        var chart = c3.generate({
        	bindto:'#chart_donut',
        	data: {
        	columns: chartData,
        	type : 'pie',
    		}
		});
});

- arrayList 생성한다. 이름 : chartData
- id 값이 ans인 태그의 길이만큼 반복문 돌린다.(문항수만큼)
- chartData변수에 배열 값을 넣는다(push)
- push 조건 : id가 ans이거나 sum_num인 태그 중 인덱스번호가 i(=eq)인 경우, 양식(form)의 값을 가져오거나 값을 설정(=val())

2) ans 접근을 위한 each 메소드 사용

클래스 값을 다르게 설정한 경우 가능하다.

<input type="hidden" class="ans{{forloop.counter0}}" name="ans" value="{{ans}}">
<input type="hidden" class="sum_num{{forloop.counter0}}" name="sum_num" value="{{row.sum_num}}">

forloop 란?

Template 태그 중 하나로 {% for %} 태그를 사용하면 리스트에 담겨 있는 항목들을 순회하면서 출력할 수 있다.

현재까지 루프를 실행한 루프 카운트를 0부터 카운트한다. ans는 인덱스번호가 0부터 시작하므로 0부터 카운트한다.

  $(function(){
        var chartData=[];

        $("[class^='ans']").each(function(){
			chartData.push([$(this).val(),$(this).next().val()]);
        })
        
        
        var chart = c3.generate({
        	bindto:'#chart_donut',
        	data: {
        	columns: chartData,
        	type : 'pie',
    		}
		});
});

- each 메소드를 통해 제이쿼리로 배열을 관리할 수 있다. each() 메서드는 매개 변수로 받은 것을 사용해 for in 반복문과 같이 배열이나 객체의 요소를 검사할 수 있는 메소드로 반복함수이다. 역할은 위의 for문과 동일하다.

- 위에서 카운트되는 값들을 그대로 this 자리에 넣어준다.

- $(this).next() 는 sum_num 값들이다.

 

 

3) 일일히 변수값 지정해주기

 

var ans1 , var ans2 등 일일히 .ans 값과 sum_num 값을 변수로 지정해주어서 배열 속의 배열 [ [배열] ] 로 넣는 방법도 있다.

4. 결과

차트가 잘 출력된다.

반응형
LIST
반응형
SMALL

+ Recent posts

반응형
LIST