본문 바로가기
LG 헬로비전 DX DATA SCHOOL/Python

Django

by 황밤 2023. 7. 26.
728x90
반응형

2023/07/26

SMALL

 

2023.07.25 - [LG 헬로비전 DX DATA SCHOOL/DATA BASE] - 데이터 베이스

 

 

데이터 베이스

2023-07-25 1. 데이터 베이스 1.1) SQR 사용에 따른 분류 RDBMS : 테이블 구조를 이용하는 데이터베이스, SQL을 이용해서 질의를 수행, 강력한 트랜잭션 기능을 활용 Oracle, MySQL(Maria DB), MS SQL Server, HANA DB, P

dxdata.tistory.com

데이터 베이스 시간에서 잠깐 다룬 Django를 조금더 자세히 다뤄보도록 하겠습니다.


**Django

 

1. 가상환경

  • 프로그램을 독립적으로 실행할 수 있는 환경
  • C와 python은 컴퓨터에 c 나 python이 설치되어 있지 않아도 실행이 가능

소스코드와 라이브러리를 합쳐서 별도의 실행 프로그램을 생성하기 때문입니다.

C나 Python을 가지고 실행 프로그램을 만들 때 사용한 라이브러리를 포함시켜서 실행 프로그램을 만들어야 한다.

 

  • 라이브러리를 별도로 설치하기 위해서 만든 환경이 가상 환경

학습을 할 때는 가상 환경을 만들지 않는 것이 좋고 서비스를 만들 때는 반드시 가상 환경을 생성해야 한다.

 

  • 자바는 JDK(자바가 제공하는 API)의 라이브러리는 포함시키지 않고 실행 프로그램을 생성하기 때문에 자바 프로그램을 실행하기 위해서는 반드시 JDK가 제공하는 라이브러리가 컴퓨터에 존재해야하는데 이것을 JRE(Java Runtime Environment)라고 한다.
  • pycharm에서는 프로젝트를 생성하면 가상환경을 활성화 해줌

 


 

2. 장고 설치 및 프로젝트 생성 과 실행

 

 

2.1) 장고 설치 : pip install django

 

  • 가상 환경을 사용하지 않으면 한 번만 설치하면 됩니다.

 

 

2.2) 장고 프로젝트 생성 : 장고를 사용할 수 있또록 디렉토리를 생성

 

  • django-admin startproject 프로젝트 이름 생성될 경로
ex) django-admin startproject dxschool .
  • 이때 프로젝트 이름으로 된 디렉토리와 manage.py가 실행됨
  • manage.py는 실행함수이므로 main 함수를 소유하고 있음.

python의 기본 entry point는 main인데 이름을 변경할 수 있다.

실행 파일의 기본 이름은 main.py 이다.

 

 

 

2.3) 애플리케이션 생성 : 실제 실행되는 프로그램을 생성

 

python manage.py startapp 애플리케이션이름(manage.py의 위치가 어딨는지 찾고, 그 위치에서 실행)
저는 svapp으로 짓고 시작했습니다.

 

 

 

2.4) 애플리케이션 실행

 

python manage.py runserver 외부에서접속할 IP : 포트번호

 

  • 외부 접속할 IP : 포트번호를 생략시, 로컬에서만 접속이 가능.
  • 따라서 127.0.0.1 : 8000 입력!
127.0.0.1(Loop Back - 0::0::0::1) : 자기 컴퓨터를 지칭하는 IP
  • localhost와 같지만, localhost는 내부에서 접속하는 형태이고, 127.0.0.1 은 외부로 나갔다가 접속하는 개념
  • 127.0.0.1 은 방화벽에 의해 사용이 막힐 수도 있음.

 

  • runserver의 의미는 'demon' 즉, 백그라운드로 서버를 계속 운영함을 의미한다.
demon : 실행 중인 것(Thread)이 있으면 계속 동작

 


 

3. 프로젝트에서 생성해주는 파일

 

 

 

3.1) 프로젝트의 settings.py 파일

 

  • 외부 접속 가능한 ip 설정 : 로컬에서만 접속하도록 기본 설정되어 있음.
  • 시간 대역 설정 : 기본 시간 대역이 UTC로 되어있어, 배포 시엔 수정이 필요
  • 접속할 수 있는 데이터베이스 설정 : 기본적으로 sqlite3 사용
  • 애플리케이션 등록 : 애플리케이션 신규 생성시, settings.py에 등록(INSTALLED_APP)하지 않으면 실행이 되지 않음. 

 

 

 

3.2) 시간 대역과 애플리케이션 등록

 

  • 프로젝트의 settings.py 파일에서 TIMEZONE을 수정

    -> TIME_ZONE = Asia/Seoul

 

  • 프로젝트의 settings.py 파일에서, INSTALLED_APP 항목에서 자신의 앱을 "문자열 형태"로 추가

 

 

3.3) 프로젝트의 urls.py

 

  • 클라이언트의 요청 URL을 처리할 함수나 메서드를 등록하는 파일
  • 여기서 등록된 요청만 서버는 처리할 수 있습니다.

 

 

3.4) 애플리케이션의 models.py

 

  • 관계형 데이터 베이스와 연동할 모델을 등록하는 부분
  • 이 부분을 수정하면 2개의 명령어를 수행해야 한다.
python manage.py make migrations
python manage.py migrate(테이블을 생성)
  • migration이 실행되지 않으면, migrations 디렉토리의 __init__.py 파일을 삭제하고 다시 수행

 

 

3.5) 애플리케이션의 views.py

 

  • 클라이언트의 요청을 처리할 로직을 작성하거나 호출하는 파일
  • 함수로 생성 혹은 클래스로 만들 수 있다.
  • 대부분의 django 샘플 코드에서는 여기에 직접 코드를 작성하지만, 실무에서는 별도의 로직 파일을 작성하고, views.py에서는 그 로직을 불러올이다.
  • django의 view는 다른 프레임워크의 Controller의 역할을 수행하는데 Controller는 클라이언트의 요청을 받아서 필요한 로직을 호출하고 그 결과를 화면에 출력하도록 전달하거나 데이터를 클라이언트에게 전송하는 역할만 수행
  • 대다수의 django 샘플 코드가 실무와 다르게 간단한 작업만 수행하기 때문에 로직을 바로 작성

 

 


 

 

4. 관리자 기능 활성화

 

 

 

 

4.1) 관리자 테이블 생성

 

python manage.py migrate

authentication(인증) : 로그인

authorization(인가) : 권한

 

 

4.2) 관리자 생성

 

python manage.py createsuperuser
  • id, pw, e-mail 을 입력
  • 비밀번호는 8자 이상으로 설정해야함.

 

 

4.3) 관리자 생성 여부 확인

 

  • 서버를 실행 (python manage.py runserver)
  • 127.0.0.1:8000/admin/ 으로 접속하여 로그인 수행

 

 


 

 

5. 요청을 받아서 처리

 

5.1) 클라이언트에게 결과를 전송하는 방식

 

  • html을 만들어서 전송

단순하게 html을 전송

서버에서 생성한 데이터와 함께 html을 만들어서 전송 - Template Engine 이용

 

  • 데이터만 전송 : 최근에는 이 방식을 선호

 

 

5.2) 클라이언트의 요청이 왔을 때 html 코드를 만들어서 전송

 

  • url을 등록 : urls.py
from django.contrib import admin
from django.urls import path
from svapp import views

urlpatterns = [
    path("admin/", admin.site.urls),
    #현재는 admin 만 가능한 상태

    # "" -> localhost:8000을 처리 svapp 의 views.py 파일의 index 함수가 이를 처리할 것이다는 의미
    path("", views.index)

 

 

  • urls.py에 등록된 함수를 생성 - views.py
from django.shortcuts import render

# Create your views here.


from django.http import HttpResponse

#요청을처리하는 함수의 매개변수는 request
#request 객체 안에는 클라이언트에 대한 정보가 저장되어 있음
def index(request) :
    return HttpResponse("<h1>Do You Know Dr.Hong?</h1>")
  • 이 방법을 이용하면 많은 내용을 출력하기 어려움.

 

  • 실행 결과

서버 실행 후, 결과 확인

 

 

5.3) HTML 파일을 만들어서 출력

 

  • URL을 처리할 함수를 설정 - urls.py
from django.contrib import admin
from django.urls import path
from svapp import views

urlpatterns = [
    path("admin/", admin.site.urls),
    #현재는 admin 만 가능한 상태

    # "" -> localhost:8000을 처리 svapp 의 views.py 파일의 index 함수가 이를 처리할 것이다는 의미
    path("", views.index),

    path("display/", views.display)

 

  • 요청을 처리할 함수를 생성 - views.py
from django.http import HttpResponse

#요청을처리하는 함수의 매개변수는 request
#request 객체 안에는 클라이언트에 대한 정보가 저장되어 있음
def index(request) :
    print(dir(request))
    return HttpResponse("<h1>Do You Know Dr.Hong?</h1>")

def display(request) :
    return render(request, "display.html")

 

  • 애플리케이션의 templates 디렉토리에 html 파일을생성 (templates의 위치는 views.py 와 동일  
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Django</title>
</head>
<body>
    <h2 style="color:red">그쪽도 홍박사 님을 아세요?</h2>
</body>
</html>

 

 

5.4) 템플릿 엔진을 이용해서 서버가 만든 데이터를 HTML에 출력

 

  • urls.py에 가서 요청을 생성
path("template", views.template)

 

  • views.py에서 template 함수 작성
def template(request):
    msg = "저는 홍박사입니다"
    #HTML에 데이터를 전송하고자 하면, 세번째 매개변수에 디셔너리를 만들어서
    #데이터 이름과 데이터를 기재
    return render(request, "template.html", {"msg":msg})

 

  • templates 디렉토리에 temlpate.html 작성
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h3>데이터:{{msg}}</h3>
</body>
</html>

 

  • 서버가 전달해 준 데이터를 출력하고자 하는 경우는 {{  }} 안에 키를 설정하면 됩니다.

 

 

5.5) 템플릿 엔진에서 if와 for 사용

 

 

{% if 조건 %}

  • elif 와 else 도 동일한 방법으로 사용 가능

{% end if}

 


 

{% for 임시변수 in 데이터 모임 %}

 

 

{% endfor %}

 

 

  •  날짜를 포맷에 맞추어서 출력

{{날짜|date:포맷}} 

 

 

  • 문자열은 함수를 적용

{{문자열|문자열메서드}}

 

 

  • views.py 파일에서 temlplate 요청을 처리하는 함수 수정
def template(request):
    age = 54

    data = ["Stack", "Queeu", "Deque", "Linked List", "Tree", "Graph", "Array"]
    #msg = "저는 홍박사입니다 HELLO"
    person = {"name":"svng", "age" : 26}
    #HTML에 데이터를 전송하고자 하면, 세번째 매개변수에 디셔너리를 만들어서
    #데이터 이름과 데이터를 기재
    return render(request, "template.html", {"age":age, "data":data})

 

 

  • template.html 내용 수정
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>홍박사</title>
</head>
<body>
    <h3>
        {% if age >= 10 %}
            나이가 많음
        {% else %}
            나이가 많지 않음
        {% endif %}
    </h3>
    <ul>
        {% for temp in data %}
            <li>
                {{temp}}
            </li>
        {% endfor %}
    </ul>
</body>
</html>

 

 

  • 실행 결과

: 나이가 많음

  • Stack
  • Queeu
  • Deque
  • Linked List
  • Tree
  • Graph
  • Array

 


 

 

6. Django의 Model

 

 

 

6.1) Model

 

  • 데이터 서비스를 제공하는 Layer 
  • Django 에서는 Model을 애플리케이션 내의 models.py 파일에 작성
  • Model 클래스는 관계형 데이터베이스의 Table 과 1:1 로 매핑됩니다.
  • Model 클래스 안에 만든 속성은 Table 의 컬럼과 1:1 로 매핑됩니다.
  • Primary Key를 설정하지 않으면 Table을 만들 때 자동으로 ID 컬럼이 생성됩니다.
  • 속성을 만들 때는 클래스 변수로 만들어야 하고 각 속성에 맞는 Field 클래스 객체(데이터베이스 자료형)를 생성해서 할당
  • Field 클래스 객체를 생성해서 할당할 때 옵션을 설정하게 되는데 필수 옵션이 있는 경우도 있습니다.

문자열은 최대 길이를 지정해야 합니다.

 

MySQL 변수 선언시 :
varchar(10) 로 문자열의 길이를 제한했었음 
int

 

 

 

6.2) Model의 필드 타입

 

 

  • CharField : 문자열 저장에 사용되는데 max_length 속성을 이용해서 최대 길이를 설정해야 한다. 

파생 클래스(상속을 받은 클래스, 하위 클래스) 로 EmailField, GenericIPAddressField, CommaSeparatedIntegerField, FilePathField, URLField 등이 있습니다.

 

  • TextField : 대용량 문자열
  • IntegerField : 정수
  • BooleanField 
  • DataTimeField
  • DecimalField : 소수
  • BinaryField
  • FileField
  • UUIDField : UUID는 식별하기 위한 코드(숫자와 문자로 구성)

 

 

 

6.3) 필드 옵션

 

  • null : null 허용 여부
  • blank : 필수 여부(True를 설정하면 옵셔널이 되고 False를 설정하면 필수)
  • primary_key
  • unique
  • default
  • db_column 으로 컬럼이름을 속성이름과 다르게 하고자 할 때 사용

 

 

 

6.4) 데이터 베이스 설정

 

 

 

 

 

6.5) MySQL 사용

 

  • mysqlclient 설치 : pip install mysqlclient
MAC은 설치가 안되는 경우에 아래 명령을 수행
$brew install mysql
$brew install openssl

 

  • settings.py 파일에서 접속 정보 수정
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "svng",
        "USER": "root",
        "PASSWORD": "252585",
        "HOST": "127.0.0.1",
        "PORT": "3306"
    }
}

 

  • models.py 파일에 테이블과 연결될 모델을 생성
class Item(models.Model) :
    itemid = models.CharField(max_length=50, primary_key=True)
    itemname = models.CharField(max_length=50)
    price = models.IntegerField()
    description = models.CharField(max_length=50)
    pictureurl = models.CharField(max_length=50)

 

  • 모델을 만들고 데이터베이스에 반영
python manage.py makemigrations
python manage.py migrate

=> 명령 수행시 관리자를 위한 테이블과 models.py 만든 클래스의 테이블을 생성하는데, 이 때 테이블의 이름은 애플리케이션의 이름_모델이름

 

이후 DBeaver 에서 migrate을 통해 만든 table이 svapp_items 로 생성되었음을 알 수 있다.

DBeaver에서 Django와 Model의 연결 확인

 

테이블 이름 변경시 , 위의 두 명령어를 다시한번 수행!

django 프로젝트 생성
pip install django
pip install mysqlclient
python manage.py startproject 프로젝트 명 .
python manage.py startapp 앱이름
settings.py -> INSTALLED_APP 에 내 앱 추가
models.py -> 모델 클래스 생성
python manage.py makemigrations
python manage.py migrate

mysql 확인 
DBeaver 
-> show tables;
테이블 이름은 애플리케이션이름_클래스 이름 으로 등록을 확인 가능

데이터 조회

 

  • 조회 방법
모델 클래스 이름.objects().조회메서드() 형태로 조회
  • 조회 메서드
  • all : 테이블의 모든 데이터 조회
  • get(기본키=값) : 키가 값과 같은 1개만 조회
  • filter(필드 이름 연산자 값) : 조건에 맞는 데이터만 조회
  • exclude(필드 이름 연산자 값) : 조건에 맞지 않는 데이터만 제외하고 조회
  • count() : 데이터 개수
  • order_by() : 정렬할 필드 이름을 나열하는데 필드 이름 앞에 -를 붙이면 내림차순
  • distinct(필드이름) : 필드 중복 제거
  • first(), last() : 처음, 마지막 데이터 조회

 

 

조회를 위해서 데이터 베이스에 접속하여 샘플 데이터를 삽입

 

어플리케이션 디렉토리에 templates 디렉토리를 생성

 

templates 디렉토리에 index.html 파일을 생성

 

# urls.py 수정 완료

from django.contrib import admin
from django.urls import path
from svapp import views
urlpatterns = [
    path("admin/", admin.site.urls),
    path("", views.index)
]

# urls.py 수정 완료

# models.py 에 클래스 생성

from django.db import models

# Create your models here.

class Item(models.Model):
    itemid = models.CharField(max_length=50)
    itemname = models.CharField(max_length=50)
    price = models.IntegerField()
    description = models.CharField(max_length=100)
    pictureurl = models.CharField(max_length=100)

# 모델 클래스 생성완료


#views.py 수정

from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
from svapp.models import Item
def index(request):
    #전체 데이터 가져오기
    data = Item.objects.all()
    return render(request, 'index.html',{'data':data})
    
#views.py 수정완료

#templates 디렉토리 내 index.html 수정

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  {% for item in data %}
    <div>
      {{item.itemid}} - {{item.itemname}} - {{item.price}}
    </div>
  {% endfor %}}
</body>
</html>

index.html 수정 완료

 

  • index.html 파일의 제목을 출력하는 부분을 수정
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  {% for item in data %}
    <div>
      {{item.itemid}} -<a href="detail/{{item.itemid}}"> {{item.itemname}} </a>- {{item.price}}
    </div>
  {% endfor %}
</body>
</html>

 

  • urls.py 파일에 detail 요청을 받을 내용을 삽입
from django.contrib import admin
from django.urls import path
from svapp import views
urlpatterns = [
    path("admin/", admin.site.urls),
    path("", views.index),
    path("detail/<str:itemid>", views.detail)

 

  • views.py 에 detail 함수를 추가
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
from svapp.models import Item
def index(request):
    #전체 데이터 가져오기
    #data = Item.objects.get(itemid=1) #이 경우 1개이므로 반복문 사용이 안됨
    data = Item.objects.all()
    return render(request, 'index.html',{'data':data})

def detail(request, itemid): #주소 뒤에 변수가 붙는다면 그 변수 그대로 사용
    item = Item.objects.get(itemid = itemid)
    print(item)
    return render(request, 'detail.html',{'item':item})

 

 

  • 이후 이 기능을 실행해줄 detail.html 파일을 작성한다
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>상세설명</title>
</head>
<body>

        <div>
            이름 : {{item.itemname}}</br>
            가격 : {{item.price}}</br>
            설명 : {{item.description}}</br>
        </div>
</body>
</html>

 

어려워 보이지만, 이는 python 과 html을 동시에 활용하고, key, value를 이용하는 dict의 형태로써 작용되기 때문입니다.

 

구조만 본다면 어렵진 않아요

 

  • models.py 에 클래스를 통해 table 생성 후 mysql 연결
  • mysql(DBeaver 활용)에서 해당 table에 내용 삽입
  • python 가상환경에서 views.py, urls.py 를 통해서 원하는 기능 구현
  • 구현할 세부 내용을 templates 디렉토리에서 html을 통해 활용
  • 결과 확인

detail을 통해 클라이언트에게 요청을 받아 정보를 제공하는 과정에서 get / post를 사용하는데,

get은 검색을할 때 주로 이용함. -> 빠르지만 보안에 취약함. 255자 한계

post는 보안에 강하지만 느림, 용량에 제한이 없음.

로그인 과정은 검색이지만 get 이 아닌 post를 사용함. for security

 

get/post 를 통한 클라이언트 서버 정보처리, 출처 : 송준호우

 

 

이제 서버에서 client 에게 정보를 넘겨줄 때, get과 post 방식에서는 어떻게 넘겨주게 되는지 그리고 그 데이터를 어떻게 읽는지 알아보겠습니다.

 

 


8. 파라미터 전송 및 읽기

 

 

8.1) 웹 클라이언트가 웹 서버에게 요청을 하는 방법

 

  • a 태그의 href 속성에 url을 작성한 후 클릭
  • form을 만들고 submit을 수행하는 경우
  • ajax 이용 - 비동기적으로 요청, 다른 작업을 수행하면서 요청을 처리해달라고 하는 방식(연결이 끊어져도 화면이 지워지지 않음)
  • web socket 이용 - 계속 연결해두고 주고 받는 방식
  • 브라우저에 URL을 직접 입력 : 메인 페이지를 접속할 때를 제외하고는 사용하지 않습니다.
http 나 https 요청 처리

Client 가 서버와 연결 가능한 지 확인하고 서버에 요청을 전송
서버는 요청을 처리한 후 응답을 전송합니다.
연결이 해제됩니다.

 

8.2) parameter

 

  • 웹 클라이언트가 웹 서버에게 전송하는 데이터
  • 전송방식 : GET, POST

 

GET :

  • URL에 파라미터를 붙여서 전송하는 방식
  • 자동 재전송이 된다는 장점
  • 데이터 크기에 제약이 있고 보안이 취약합니다.
  • 일반적으로 데이터 크기가 작고 보안이 중요하지 않은 요청에 사용 : 조회
  • 데이터에 숫자 나 영문이 아닌 것이 있으면 Encoding 해서 전송해야 합니다.

 

 

POST :

  • 파라미터를 헤더나 바디에 숨겨서 전송하는 방식
  • 숨겨서 전송하기 때문에 보안이 GET 방식보다 우수하고 데이터의 크기에 제한이 없습니다.
  • 인코딩해서 전송할 필요가 없는데, 서버에서 인코딩처리를 수행하기 때문이다.
  • 일반적으로 삽입, 삭제, 갱신 작업에 사용을 하고 조회 작업 중에서도 노출되면 안되는 정보를 이용하는 경우에는 POST를 사용한다.
  • 최근에는 삽입, 삭제, 갱신 작업을 구분하기 위해서 삽입은 POST, 수정은 PUT, 삭제는 DELETE 방식으로 요청합니다.

 

 

8.3) 파라미터 작성

 

  • GET 방식의 파라미터 작성

- URL 뒤에 파라미터를 이름 과 함께 작성하는 방식 - 파라미터가 2개 이상일 때 주로 이용

요청 경로?이름=값&이름=값.....

https://news.naver.com/main/main.naver?mode=LSD&mid=shm&sid1=104

이 경우는 mode, mid, sid1 이라는 파라미터가 같이 전송되는 것이다.

 


 

- URL에 파라미터를 포함시키는 경우 - 파라미터가 1개 일 때

https://dxdata.tistory.com/27

이 경우는 27이 파라미터입니다. -> URL에 포함시켜서 전송합니다.

상세보기를 구현할 때 많이 이용합니다.

 

form을 만들어서 데이터를 전송하는 경우는 첫번째 방법으로 전송됩니다.

 

 


 

  • POST 방식의 파라미터 전송

1. formdata 로 전송하는 방식

 

 

 

2. JSON 형식으로 전송하는 방식

 

 

 

8.4) django 서버에서 파라미터 읽기

 

  • 전송된 방식에 따라 읽는 방법이 달라집니다.
  • url에 포함시켜서 파라미터를 전송하는 경우
urls.py에서 요청 처리 부분을 설정할 때
path('요청경로/<파라미터자료형:파라미터이름>', 처리할 함수 나 클래스)

path('detail/<str:itemid>', views.detail)

 

views.py에서 요청을 처리할 때
def 함수이름(request, 파라미터 이름) :
파라미터 이름에 데이터가 저장됩니다.

def detail(request, itemid):

 

 

어려운 것이 아니라 익숙하지 않은 것 뿐이다.
보상은 절대로 노력없이 이루어지지 않는다.
노력은 절대로 반비례하지 않는다.
시작은 결과에 영향을 주긴하지만 결정적인 영향은 그 과정에서 나온다.

-it 황밤-

 

 

 

 

 

 


 

 

 

반응형
LIST