반응형
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

Spring에서 만들었던 쇼핑몰 페이지를 그대로 디장고(Django)로 바꿔 옮기자.


1. 초기 상태

현재 받은 파일에서는 회원가입 기능과 로그인 기능은 구현 되어 있는 상태.

urls.py에 대부분의 페이지 path가 연결되어 있다.

 

 

▼views.py

더보기

1. 아직 기능 구현 하지 않은 것들은 jsp 파일로 렌더링만 해놓음.

from django.shortcuts import render, redirect

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

from shoppingmallPrj.models import getLoginChk, client_insert


def home(request):
    return render(request, 'shoppingmallPrj/index.jsp')


def shop_cart(request):
    return render(request, 'shoppingmallPrj/shop_cart.jsp')


def my_page(request):
    return render(request, 'shoppingmallPrj/my_page.jsp')


def product_details(request):
    return render(request, 'shoppingmallPrj/product_details.jsp')


def shop(request):
    return render(request, 'shoppingmallPrj/shop.jsp')


def index(request):
    return render(request, 'shoppingmallPrj/index.jsp')


def manager(request):
    return render(request, 'shoppingmallPrj/manager.jsp')


def qna_board(request):
    return render(request, 'shoppingmallPrj/qna_board.jsp')


def checkout(request):
    return render(request, 'shoppingmallPrj/checkout.jsp')


def shop_type(request):
    return render(request, 'shoppingmallPrj/shop_type.jsp')


def shop_search(request):
    return render(request, 'shoppingmallPrj/shop_search.jsp')


def manager_customer_detail(request):
    return render(request, 'shoppingmallPrj/manager_customer_detail.jsp')


def manager_product_detail(request):
    return render(request, 'shoppingmallPrj/manager_product_detail.jsp')


def manager_pay_all(request):
    return render(request, 'shoppingmallPrj/manager_pay_all.jsp')


def manager_add_product(request):
    return render(request, 'shoppingmallPrj/manager_add_product.jsp')


def manager_qna_board(request):
    return render(request, 'shoppingmallPrj/manager_qna_board.jsp')

 

2. 로그인 / 로그인샵 / 로그인카트 * 로그아웃 / 회원가입 -> 총 9개

@csrf_protect
def login(request):
    if 'client_id' in request.session:
        return redirect('/index')
    if request.method == 'POST':
        client_id = request.POST['client_id']
        password = request.POST['password']
        print('client_id :', client_id)
        print('password :', password)
        # --------------------------------------------------------------
        res = getLoginChk(client_id, password)
        print('=' * 30)
        print(res)
        if len(res) > 0:
            print('로그인 성공')
            request.session['client_id'] = client_id
            request.session['client_name'] = res[0][0]
            return redirect('/shoppingmallPrj')
        else:
            print('로그인 실패')
            msg = '아이디나 비밀번호가 잘못 되었습니다.'
            return render(request, "shoppingmallPrj/index.jsp", {"error": msg})
    return render(request, 'shoppingmallPrj/index.jsp')


@csrf_protect
def login_shop(request):
    if 'client_id' in request.session:
        return redirect('/shoppingmallPrj/shop')
    if request.method == 'POST':
        client_id = request.POST['client_id']
        password = request.POST['password']
        print('client_id :', client_id)
        print('password :', password)
        # --------------------------------------------------------------
        res = getLoginChk(client_id, password)
        print('=' * 30)
        print(res)
        if len(res) > 0:
            print('로그인 성공')
            request.session['client_id'] = client_id
            request.session['client_name'] = res[0][0]
            return redirect('/shoppingmallPrj/shop')
        else:
            print('로그인 실패')
            msg = '아이디나 비밀번호가 잘못 되었습니다.'
            return render(request, "shoppingmallPrj/shop.jsp", {"error": msg})
    return render(request, 'shoppingmallPrj/shop.jsp')


@csrf_protect
def login_cart(request):
    if 'client_id' in request.session:
        return redirect('/shoppingmallPrj/shop_cart')
    if request.method == 'POST':
        client_id = request.POST['client_id']
        password = request.POST['password']
        print('client_id :', client_id)
        print('password :', password)
        # --------------------------------------------------------------
        res = getLoginChk(client_id, password)
        print('=' * 30)
        print(res)
        if len(res) > 0:
            print('로그인 성공')
            request.session['client_id'] = client_id
            request.session['client_name'] = res[0][0]
            return redirect('/shoppingmallPrj/shop_cart')
        else:
            print('로그인 실패')
            msg = '아이디나 비밀번호가 잘못 되었습니다.'
            return render(request, "shoppingmallPrj/shop_cart.jsp", {"error": msg})
    return render(request, 'shoppingmallPrj/shop_cart.jsp')


# 로그아웃 처리
def logout(request):
    del request.session['client_id']
    del request.session['client_name']
    return redirect('/shoppingmallPrj')


def logout_shop(request):
    del request.session['client_id']
    del request.session['client_name']
    return redirect('/shoppingmallPrj/shop')


def logout_cart(request):
    del request.session['client_id']
    del request.session['client_name']
    return redirect('/shoppingmallPrj/shop_cart')


@csrf_protect
def sign_in(request):
    client_info = (request.POST['client_id'], request.POST['password'],
                   request.POST['client_name'], request.POST['addr'],
                   request.POST['phone'], request.POST['email'])
    client_insert(client_info)
    return redirect('/shoppingmallPrj')


@csrf_protect
def sign_in_shop(request):
    client_info = (request.POST['client_id'], request.POST['password'],
                   request.POST['client_name'], request.POST['addr'],
                   request.POST['phone'], request.POST['email'])
    client_insert(client_info)
    return redirect('/shoppingmallPrj/shop')


@csrf_protect
def sign_in_cart(request):
    client_info = (request.POST['client_id'], request.POST['password'],
                   request.POST['client_name'], request.POST['addr'],
                   request.POST['phone'], request.POST['email'])
    client_insert(client_info)
    return redirect('/shoppingmallPrj/shop_cart')

 

▼urls.py

더보기

등록된 path 들. 이번 과제에서 내가 정의할 것은 상품 등록에 해당하는 manager_add_product와 등록된 상품을 볼 수 있는 manager_product_detail를 정의해야 한다.

from django.urls import path

from shoppingmallPrj import views
#
urlpatterns=[
    path("",views.home),
    path("shop_cart",views.shop_cart),
    path("my_page",views.my_page),
    path("product_details",views.product_details),
    path("shop",views.shop),
    path("index",views.index),
    path("manager",views.manager),
    path("qna_board", views.qna_board),
    path("checkout", views.checkout),
    path("login", views.login),
    path("logout", views.logout),
    path("logout_shop", views.logout_shop),
    path("logout_cart", views.logout_cart),
    path("sign_in", views.sign_in),
    path("login_shop", views.login_shop),
    path("login_cart", views.login_cart),
    path("shop_type", views.shop_type),
    path("shop_search", views.shop_search),
    path("manager_customer_detail", views.manager_customer_detail),
    path("manager_product_detail", views.manager_product_detail),
    path("manager_add_product", views.manager_add_product),
    path("manager_qna_board", views.manager_qna_board),
]

2.  manager_add_product의 input 데이터 DB로 보내기

1) add_product 로 이동

상품 추가 페이지에서 상품 등록을 누르면,

add_product로 가도록 링크를 걸어두었다.

def manager_add_product(request):
    return render(request, 'shoppingmallPrj/manager_add_product.jsp')

manage_add_product.jsp 로 넘어오면 add_priduct로 쏜다.

따라서 add_product 라는 이름의 뷰를 지정해서 기능을 구현해야 한다.

 

 

-> 입력값 오라클로 보내기

action 누르면 add_product(정의하기-> insert 하는거, 뷰에서 실행해서 리다이렉트 관리자 페이지로)로 가는거 그걸 뷰에서 정의 그리고 모델에서 오라클로 보내고.

 

2) 상품의 시퀀스 만들기(Product_info_seq)

create sequence Product_info_seq increment by 1 start with 1;

 

3) 상품을 추가하는 함수 만들기(views.py)

product_info에 각 카테고리의 값을 post로 담아서 product_insert의 안의 함수로 넣어줌.

다 되면 manager로 이동

@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')

 

4) 상품을 추가하는 함수 만들기(models.py)

views.py에서 만들어 놓은 product_info라는 매개변수의 값을 가져와서 sql문 실행

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()

5) urls.py 등록

6) 실행

데이터 입력
오라클에 잘 들어간다


[ 에러 모음 ]


1. MultiValueDictKeyError

해결책 : PRODUCT_NAME 등 컬럼명을 전부 소문자로 바꿔줬더니 에러 해결.

 

 

2. ORA-01400: cannot insert NULL into

POST.get('PRODUCT_NAME','')도 써봤지만 not null로 지정해주었기 때문에 소용이 없었다. 그냥 post로 하고 1번 방법으로 해결.

[ 차이점 ]
request.POST['title']

request.POST['title']는 request 로 넘어온 POST 값을 딕셔너리(dictionary)형태로 반환을 해 준다. 딕셔너리는 파이썬 (python) 문법에 의해서 key 값과 value 값으로 존재하기 때문에 ['...'] 인 key 값을 이용해서 value 값을 리턴해 준다. 그런데 여기서 value 값이 존재하지 않는다면 MultiValueDictKeyError을 일으킨다.

request.POST.get('title', '')

반면에 request.POST.get('title') 에선 존재하지 않는 key 값을 반환해야 한다면 None 을 반환해 주고, request.POST.get('title', '') 로 할 경우엔 존재하지 않는 key 값을 반환할때 default 값을 지정해 줄 수 있다.

 

3. CSRF 검증에 실패했습니다. 요청을 중단하였습니다.

CSRF의 예외처리를 안했다. @csrf_exempt를 붙이고 수입하면 해결.

 

 

4. IntegrityError

 

add_product에서 FK인 category_type_id나 category_gender_id 를 아무 값도 안넣고 null로 두어서 에러남.

DB를 보면 id 컬럼이 NOT NULL로 되어있음을 확인할 수 있다.

=> user_id가 NULL이 되지 않도록 오라클에 아무 값이나 넣어주자.

추가하고 commit 한다

 


이제 

 

3.  manager_product_detail의 input 데이터 DB로 보내기

1) models.py에 필요한 값들 불러오기

# 상품 세부 내역
def product_detail_show():

    conn = ora.connect(database)
    cursor = conn.cursor()
    sql = "select * from product_info order by 1 desc"
    cursor.execute(sql)
    result = cursor.fetchall()
    print(result)
    cursor.close()
    conn.close()
    return result

 

 

2) manager_product_detail에 models.py에서 받아온 값들 집어넣기(views.py)

그 후에 product_detail에 넣은 값들 불러와.

def manager_product_detail(request):
    product_detail=product_detail_show()
    return render(request, 'shoppingmallPrj/manager_product_detail.jsp',{'product_detail':product_detail})

 

3)manager_product_detail.jsp 변경

받아왔으니까 연결시킨 jsp 중 어디에 출력할건지 범위 설정해주기


                            <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>

4) urls.py에 path 등록하기

    path("manager_product_detail", views.manager_product_detail),

 

5) 결과

 

 

+추가

원피스만 등록된다!

2번 3번도 등록해주기.

카테고리 타입에 1번만 등록해놨다...ㅎㅎ...

반응형
LIST
반응형
SMALL

스키장에서 물건을 주웠다. 그 물건을 분실물센터에 올려야하는데, 이미지를 올려야 한다. 어떤걸 개발해야할까?

 

1) 분실물 카테고리

2) 클라이언트가 사용할 앱

3) 올리는 순간 위치도 찍도록

4) 기타 등등

 

가장 중요한 것은 물건을 찾거나 찾아줄 때를 위한 알바생이 필요하다.

다행히 우리에게는 이중분류 또는 다중분류로 불리는 알고리즘 친구가 있다.

이번엔 분류 알고리즘을 써서 훈련 -> 머신러닝까지는 안하고, 준비된 파일을 이용해서 분류 앱만 만들어 보도록 하자.

 

준비된 파일에는 이미지 분류를 위한 h5 파일과 json 파일이 있다.

 

▼파일 받기

 


[ fileup  웹 페이지 기능 구현하기 ]


#자세한 세팅은 앞에 포스팅 참조

1. fileup 앱 만들기

늘 하던대로 fileup > templates > fileup > upform1.html 파일 생성

python manage.py startapp fileup

2. upform1.html 파일 만들기

3. 뷰 추가(view.py)

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

5. config/setting 추가

6. config/urls 추가

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

 

기본 세팅 끝!


본격적으로 첫 페이지의 파일 업로드 폼을 만들러 가자.


8. catdog 테이블 생성

개나 고양이의 별명(aname), 작성자, 카테로리, 데이터를 추가하기 위한 (cont clob) 등등으로 이루어져 있다.

▼clob란?

더보기

CLOB 이란?

사이즈가 큰 데이터를 외부 파일로 저장하기 위한 데이터 타입이다.

 

  • 문자열 데이터를 DB 외부에 저장하기 위한 타입이다.
  • CLOB 데이터의 최대 길이는 외부 저장소에서 생성 가능한 파일 크기이다.
  • CLOB 타입은 SQL 문에서 문자열 타입으로 입출력 값을 표현한다. 즉, CHAR(n), VARCHAR(n), NCHAR(n), NCHAR VARYING(n) 타입과 호환된다. 단, 명시적 타입 변환만 허용되며, 데이터 길이가 서로 다른 경우에는 최대 길이가 작은 타입에 맞추어 절삭(truncate)된다.
  • CLOB 타입 값을 문자열 값으로 변환하는 경우, 변환된 데이터는 최대 1GB를 넘을 수 없다. 반대로 문자열을 CLOB 타입으로 변환하는 경우, 변환된 데이터는 CLOB 저장소에서 제공하는 최대 파일 크기를 넘을 수 없다.

즉, 문자형 대용량 파일 저장 하는데 유용하고 가변길이로 잘려서 저장이 된다. 라고 생각하시면 되겠네요 ㅎㅎ 

 

BLOB이란?

바이너리 데이터를 DB 외부에 저장하기 위한 타입이다.

 

  • BLOB 데이터의 최대 길이는 외부 저장소에서 생성 가능한 파일 크기이다.
  • BLOB 타입은 SQL 문에서 비트열 타입으로 입출력 값을 표현한다. 즉, BIT(n), BIT VARYING(n) 타입과 호환되며, 명시적 타입 변환만 허용된다. 데이터 길이가 서로 다른 경우에는 최대 길이가 작은 타입에 맞추어 절삭(truncate)된다.
  • BLOB 타입 값을 바이너리 값으로 변환하는 경우, 변환된 데이터는 최대 1GB를 넘을 수 없다. 반대로 바이너리를 BLOB 타입으로 변환하는 경우, 변환된 데이터는 BLOB 저장소에서 제공하는 최대 파일 크기를 넘을 수 없다. 

즉, 컴퓨터가 인식하는 모든 파일(이진 데이터)을 저장하는 타입이다.

 

대용량 -> 4GB까지 저장이 된다.(long의 2배)

LOB 타입은 데이터를 저장하는게 아니라 DB에 저장된 LOB값의 위치 포인터를 저장하기 때문에 일반적으로 읽어오는 SELECT 구문을 사용하면 위치값만 나오게 된다.

 

출처 : http://www.cubrid.org/ko_manual41/entry/BLOB%7CCLOB


create table catndog(
num number constraint shop_num_pk primary key,
aname varchar2(100),
writer varchar2(30),
categories varchar2(10),
cont clob,
img varchar2(50),
reip varchar2(50),
mdate date);


create sequence catndog_seq
increment by 1
start with 1;

 

 

9. unform1.html에 제대로 body 채워주기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>upform1.html</title>
</head>
<body>
<h1>파일 업로드 예제</h1>
<div id="wrap">
    <form method="post" id="form1" enctype="multipart/form-data">
       {% csrf_token %}
        <p>이미지 등록</p>
        <p><input type="file" name="file1" id="file1"></p>
        <p><input type="button" value="등록" id="writeBtn"></p>
    </form>
</div>
</body>
</html>

 

10. 구글 CDN 링크를 하단 script에 입력해주기(3.5버전)

▼CDN이란?

더보기

CDN이란?

CDN(콘텐츠 전송 네트워크)은 서버와 사용자 사이의 물리적 거리를 줄여 웹 페이지 콘텐츠 로드 지연을 최소화하는, 촘촘히 분산된 서버로 이루어진 플랫폼이다.

CDN을 사용하지 않으면 콘텐츠 오리진 서버들은 모든 엔드유저의 요청에 일일이 응답해야 한다. 이는 오리진과 오리진에 막대한 트래픽을 유발하고 이후에도 엄청난 부하를 유발하여 트래픽이 과도하게 증가하거나 부하가 끊임없이 들어오는 경우 오리진에서 장애가 발생할 확률을 높인다.CDN은 오리진을 대신하여 엔드유저와 가까운 물리적 위치 및 네트워크에서 엔드유저 요청에 응답함으로써 콘텐츠 서버의 트래픽 부하를 오프로드하고 웹 경험을 개선하여 콘텐츠 제공업체와 엔드유저 모두에게 막대한 이점을 제공한다.

 

인터넷 트래픽의 절반 이상이 CDN(콘텐츠 전송 네트워크)을 통해 전송된다. CDN의 목표는 웹 페이지에 대한 요청이 이동해야 하는 물리적 거리를 줄여 요청 제출 시간과 장치에 완전히 로딩되는 웹 페이지 간의 지연 시간을 줄이는 것이다.

출처:www.akamai.com/kr/ko/cdn/what-is-a-cdn.jsp


이거 붙여넣기

 <!--구글 CDN 링크 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

헤드에 넣었다

 

11. static 아래 images 디렉토리 만들기

이제 파일 업로드 하면 거기에 사진이 들어갈 수 있도록 만들 것.

 

12. upform1 하단에 제이쿼리 쓰자.

<script>
    $(function(){
        $('#writeBtn').click(function(){
            $('#form1').attr('action','upload_success');
            $('#form1').submit();
        });
    });
</script>

 

실행 후 F12 개발자 모드 들어가서 요소를 보면(form 부분) 전송이 되는지 확인해 볼 수 있음. -> ????

 

13. 파이어폭스에서 강아지와 고양이 사진을 다운받아 보자.

14. views 가서 정의하자.

만든 것 중에 upload_success를 만들어야함.

파일 업로드 하는 방법이다.

이렇게하면 파일을 업로드 했을 때 위에서 설정한 링크로 들어간다.(이미지 폴더로)

# 업로드 링크
UPLOAD_DIR = '/home/kosmo_03/PycharmProjects/myapps/fileup/static/images/'


@csrf_protect
def upload_success(request):
    # request.FILES : enctype으로 전소오디어 온 파일 파라미터 객체
    # .name 등의 파일의 정보를 받을 수 있다.
    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 = '-'
    return render(request, "fileup/success.html", {'file_name': file_name})

15. urls 등록하기

    path('upload_success',views.upload_success),

16. success.html 파일만 대충 만들어놓고 사진 업로드 해보자

잘 들어갔다

17. success.html 수정하기

등록버튼을 누르면 사진이 나온다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>success.html</title>
    <style>
        image { width:300px }
    </style>
</head>

{% load static %}
{% static "" as baseUrl %}

<body>
<img src="{{baseUrl}}/images/{{file_name}}">


</body>
</html>

 

18. upform2.html 만들기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>upform2.html</title>
    <style>
        #wrap { width:350px; margin:auto }
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<h1>파일 업로드 예제</h1>
<div id="wrap">
    <form method="post" id="form1" enctype="multipart/form-data">
        {% csrf_token %}
        <p>강아지/고양이 이미지 등록</p>
        <p><input type="file" name="file1" id="file1"></p>
        <div>
            <img src="" id="targetImg" style="width:300px">
        </div>
        <p><input type="button" value="등록" id="writeBtn"></p>
    </form>
<script>
    $(function(){
        $('#writeBtn').click(function(){
            $('#form1').attr('action','upload_success')
            $('#form1').submit()
        });//클릭함수
        
        //html5 파일 기능
        $('#file1').change(function(){
            //업로드 파일 읽기
            let fileInfo = document.getElementById("file1").files[0];
            console.log(fileInfo)
            let reader = new FileReader();
            //readAsDataURL()을 통해 파일을 읽어들일 때 onload가 실행
            reader.onload=function(){
                document.getElementById("targetImg").src = reader.result;
            };
            if(fileInfo){
                //readAsDataURL()을 통해 파일의 URL을 읽어온다.
                reader.readAsDataURL(fileInfo);
            }
        })//chang 함수
    })//시작함수
</script>
</div>
</body>
</html>

19. 경로와 views에 main2 등록

urls.py
views.py

main2로 바로 접속하면 잘 된다.

 

20. 설치하자

pip install pillow
pip install tensorflow

텐서플로우 설치 못해서 아무것도 못했던게 엊그제 같은데ㅠㅠ

 

views.py에 import 해준다.

from PIL import Image
import tensorflow as tf
import os,glob
import numpy as np
from tensorflow.python.keras.models import load_model, model_from_json
from tensorflow.python.keras.preprocessing.image import load_img

 

21. success2.html을 만든다.

내용 일단 그냥 복붙해놓고.

 

22. views.py에 success2 추가

파일을 받아서 모델을 열어서 모델가지고 전에 올렸던 강아지나 고양이 사진을 가지고 학습해서 y_pridict(=결과값)을 출력해서 실험해보자. 예측을 하는데 도와주는 것이지, 예측에는 100프로는 없기 때문에 참고용으로 사용할 수 있다.

@csrf_protect
def upload_success2(request):
    if 'file1' in request.FILES:

        file = request.FILES['file1']
        file_name = file.name

        fp = open("%s%s" % (UPLOAD_DIR, file_name), 'wb')

        for chunk in file.chunks():
            fp.write(chunk)
        fp.close()

        # ---추가-- 어차피 개 어려운거 실행이라도 해보는게 의의-------
        # model.json 파일 열기
        json_file = open('/home/kosmo_03/PycharmProjects/myapps/fileup/static/catdog_model.json')
        loaded_model_json = json_file.read()
        json_file.close()

        # json 파일로부터 model 로드하기
        loaded_model = model_from_json(loaded_model_json)
        # json model에 가중치 값 로드하기
        loaded_model.load_weights("/home/kosmo_03/PycharmProjects/myapps/fileup/static/model.h5")
        loaded_model.compile(loss='binary_crossentopy', optimizer='adam', metrics=['accuracy'])
        # 가중치와 모델을 로드 완료
        image = Image.open("%s%s"%(UPLOAD_DIR,file_name))
        width = 64
        height = 64
        image = image.resize((width,height))

        # 이미지를 벡터화
        image = np.array(image)
        x_test = [image]
        x_test = np.array(x_test)
        x_test = x_test /255
        y_predict = loaded_model.predict(x_test)
        category = ""

        # 예측해서 50% 이면 cat, 아니면 dog
        if y_predict >= 0.5:
            category = "cat"
            print("cat",y_predict)
        else:
            category = "dag"
            print("dog",y_predict)

        # --------------- 추가 완료 -----------------------------
    else:
        file_name = '-'
    return render(request, "fileup/success2.html", {'file_name': file_name, 'y_predict':y_predict, 'category':category})

어떻게 분류할까?

이미지의 경우, 예를 들면 색이 들어간 곳은 1, 아닌곳은 0(물론 실제로 이것보다 복잡하다)으로 두는 등, 이런 식으로 벡터로 array를 만들고, 그걸 수학적으로 훈련시킨다.

그러한 데이터로 확률을 구하는 것.

23. 아까 만든 success2.html 수정

분류된 결과값이 나올 수 있도록 써주기!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>success2.html</title>
    <style>
        image { width:300px }
    </style>
</head>

{% load static %}
{% static "" as baseUrl %}

<body>
<img src="{{baseUrl}}/images/{{file_name}}">

<!-- ----------- 추가 ------------------- -->
{% if 'cat' in category %}
<p>위의 이미지는 {{y_predict}} 값으로 <b> 고양이 [{{category}}]</b>로 예측되었습니다.</p>
{% else %}
<p>위의 이미지는 {{y_predict}} 값으로 <b> 강아지 [{{category}}]</b>로 예측되었습니다.</p>
{% endif %}

<p>
    <input type="submit" value="파일업로드" onclick="location='main2'">
</p>
<!-- ----------- 추가 끝----------------- -->
</body>
</html>

 

24. urls.py 패스도 추가해주어야한다.

    path('upload_success2',views.upload_success2),

 

25. 결과

1) main

2) main2

아래 확률까지 잘 나온다.

 

반응형
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

+ Recent posts

반응형
LIST