Django (+1)

LEE EUI JOO·2023년 2월 2일
0

Web Programming

목록 보기
3/17

Python Web Programming

  • 웹 관련 라이브러리를 이용해서 직접 구현 : 프로젝트 구조부터 전부 직접 생성해야 해서 현실성이 떨어지지만 프레임워크의 구성이나 구동 방식을 이해할 때는 도움이 된다.

  • 웹 관련 프레임워크를 이용 : 빠르게 애플리케이션을 생성

    • Flask : 자유도가 높고 빠르게 애플리케이션을 만들어서 구동시켜 볼 수 있다 하지만, python에 대해 많이 알아야 한다.

    • Django : 구조를 생성해주고 이 규칙을 따라야 하므로 자유도는 높지 않다 하지만, 기본 설정이 많이 되어 있기 때문에 복잡한 애플리케이션을 개발할 때 Flask 보다 쉽게 만들 수 있다.


  • 개발 환경
    • IDE : Pycharm Community
    • Python 3.9.6 version - anaconda 로 설치
    • DB : Mariadb - Docker Container 로 띄운 상태
root@e1c64a664a16:/# mysql -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 18
Server version: 10.10.2-MariaDB-1:10.10.2+maria~ubu2204 mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| euijoodb           |
| information_schema |
| mariadb            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.001 sec)

MariaDB [(none)]> grant all privileges on euijoodb.* to 'euijoo'@'%';
Query OK, 0 rows affected (0.005 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.002 sec)

MariaDB [(none)]> exit
Bye
root@e1c64a664a16:/# mysql -u euijoo -p;
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 19
Server version: 10.10.2-MariaDB-1:10.10.2+maria~ubu2204 mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| euijoodb           |
| information_schema |
| mariadb            |
+--------------------+
3 rows in set (0.001 sec)


Django

  • python web server framework

  • python 외부 라이브러리라서 설치 필요 : pip install django

  • MTV - Model, Template, View

    • 프로그래밍을 3가지 영역으로 나누어서 수행

    • Model : Persistency Store 와 동작하는 부분

    • Template : 서버의 데이터를 화면에 출력하는 부분

    • View : 사용자의 요청(Request - URL)이 왔을 때 필요한 Business Logic 을 호출하고 그 결과를 넣어서 Template 에게 전송하는 역할 - Controller

  • Django의 구성요소

    • Model : 데이터에 대한 정의를 담고 있는 장고의 클래스

    • URLConf: URL 정의 - urls.py라는 파일에 url과 호출될 함수를 설정

    • View : 로직을 처리하는 부분 - 다른 곳에서는 Controller라고 표현하며, views.py 파일에 작성

    • Template : 화면 출력 설정 - 확장자는 html을 사용하고 여기에 Django의 템플릿 엔진을 이용해서 처리한 데이터를 출력

  • Django의 구조

    • 프로젝트 와 애플리케이션으로 구분 - 프로젝트 1개에 1개 이상의 애플리케이션 배치가 가능하다

  • 웹 생성 - mysite 라느 프로젝트를 만들고 그 안에 mydjango 라는 앱을 생성

    1. Django 설치 : pip install django
    • pip를 업데이트 해야 만 설치되는 경우가 있음
    • windows 의 경우 터미널이 power shell 로 되어 있으면 권한이 없다는 에러가 발생할 수 있음
    • windows에서 anaconda를 설치했을 때 path에 anaconda경로를 추가하지 않으면 open ssh를 이요할 수 없다는 에러가 발생하는데, 이경우 path라는 환경 변수에 anaconda 경로를 추가해주면 된다.
    1. 프로젝트 생성 : django-admin startproject 이름

    2. 앱 생성 : python manage.py startapp 이름

    3. 실행 : 터미널에서 명령어로 실행

    • python manage.py runserver [IP주소 : 포트번호]

Virtual Env 사용


pip install Django

(venv)  euijoolee@EUIJOOui-MacBookAir  ~/PycharmProjects/mysite  pip install django
Collecting django
  Downloading Django-4.1.6-py3-none-any.whl (8.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.1/8.1 MB 65.2 MB/s eta 0:00:00
Collecting asgiref<4,>=3.5.2
  Downloading asgiref-3.6.0-py3-none-any.whl (23 kB)
Collecting sqlparse>=0.2.2
  Downloading sqlparse-0.4.3-py3-none-any.whl (42 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 42.8/42.8 kB 5.0 MB/s eta 0:00:00
Installing collected packages: sqlparse, asgiref, django
Successfully installed asgiref-3.6.0 django-4.1.6 sqlparse-0.4.3

[notice] A new release of pip available: 22.3.1 -> 23.0
[notice] To update, run: pip install --upgrade pip



데이터 베이스 연동 방법

  • 데이터베이스 제조사에서 제공하는 API를 이용

    SQL을 직접 작성해서 데이터베이스 드라이버에게 전달해서 데이터베이스를 사용
    데이터 베이스 마다 드라이버가 다르고 연결하는 방법도 달라서 프로그래밍이 쉽지 않음

  • Framework의 연동 기술을 이용

  1. SQL Mapper

    프로그래밍 코드 와 SQL을 분리해서 작성
    코드의 가독성이 높아져서 유지 보수가 위의 방법보다는 쉽고 개발자들이 대부분 SQL을 알고 있기 때문에 접근하기가 쉽지만, 효율이 떨어짐
    Mabatis 가 대표적인 SQL Mapper 인데 국내에서는 SI업계에서 주로 사용

  2. ORM

    객체 지향 언어의 클래스(인스턴스)와 RDBMS(관계형 데이터베이스)의 테이블을 매핑시켜 사용하는 방식
    SQL없이 관게형 데이터베이스 사용이 가능
    데이터베이스 종류에 상관없이 동일한 인터페이스로 사용 가능 - 데이터베이스 종류를 변경하는 것은 설정의 변경만으로도 된다
    공부하기 어렵다는 단점이 있지만 효율이 높기 때문에 솔루션 업체에서 주로 이용
    Java 의 JPA, Python의 Django 등이 대표적인 ORM 프레임워크


settings.py

ALLOWED_HOSTS = []

* 실행할 서버의 IP 설정인데 비워두면 localhost, 127.0.0.1 가 설정되고 혹은 루프백 주소를 기입해도 된다.
* 개발 모드인 경우는 비워두거나

------------------------------
* 프로젝트에 실행할 APP을 등록하는 부분 - Application을 추가한 경우 실행을 위해서 추가

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
------------------------------
* 사용할 데이터 베이스 설정

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
------------------------------
* 시간대 설정

TIME_ZONE = 'Asia/Seoul'
------------------------------
* static 파일의 경로 : css 나 js 또는 이미지 처럼 절대로 변경되지 않는 외부 자원을 static 이라고 한다

STATIC_URL = 'static/'


실행

(venv)  ✘ euijoolee@EUIJOOui-MacBookAir  ~/PycharmProjects/mysite  cd mysite                                
(venv)  euijoolee@EUIJOOui-MacBookAir  ~/PycharmProjects/mysite/mysite  python manage.py runserver localhost:8000
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
February 02, 2023 - 11:35:16
Django version 4.1.6, using settings 'mysite.settings'
Starting development server at http://localhost:8000/


관리자 모드

  • Django 는 관리자 모드를 탑재

  • 관리자 생성 : python manage.py createsuperuser


View 및 Template 처리

  • View 는 url 요청이 왔을 때 호출될 함수를 설정
  • Template는 View 설정에 따라 실제 데이터를 출력하는 화면을 만드는 것
  1. 새로 추가한 App을 사용할 수 있도록 등록
    프로젝트 디렉토리 /setting.py 파일의 INSTALLED_APP 부분에 앱 이름을 추가

  1. URL Mapping

    • urls.py 파일에 사용할 URL 과 호출될 함수를 연결
      이 때 사용되는 함수는 path 함수

    • path 함수는 2개의 필수 인자 와 2개의 선택 인자를 받음
      필수 인자는 route 와 view인데 route는 처리할 URL이고 view는 호출될 함수

    • kwargs 는 선택인자인데 URL에서 추출된 항목 이외의 데이터를 전달하고자 할 때 사용하는 것으로 python의 dict 타입으로 전달해야 한다

    • name 은 이름

<메인 앱의 urls.py>

"""
from django.contrib import admin
from django.urls import path

# 실제 함수가 위치할 파일을 Import
from mydjango import views


urlpatterns = [
    path('admin/', admin.site.urls),
    # 기본 요청이 왔을 때 mydjango의 views.py 파일의 index 함수가 처리
    path("",views.index)

]
< 다른 앱의 views.py>

from django.shortcuts import render

# Create your views here.
from django.http import HttpResponse

# 클라이언트의 요청을 처리하는 함수
# 이 함수의 매개변수는 HttpRequest 타입인데
# 이 타입은 클라이언트의 정보를 가진 클래스

def index(request):
    # 클라이언트에게 문자열 응답을 전송
    return HttpResponse("Hello Django");


View Template 사용

  • HTML 파일에 서버에서 처리한 데이터를 출력하는 것

  • Template Engine : 서버가 처리한 데이터를 HTML 사이에 출력하도록 도와주는 라이브러리이고 Django는 내장하고 있음 하지만, 최근에는 이 방식의 출력을 권장하지는 않음

  • mydjango/viwes.py를 수정해서 html 을 출력하도록 변경

def index(request):
    # 클라이언트에게 문자열 응답을 전송
    #return HttpResponse("Hello Django");

    msg = 'use first Template Engine'
    # template 디렉토리에 있는 index.html 파일로 출력하는데
    # 데이터를 message 라는 이름으로 전달
    # request 와 함께 전달해서 화면을 만드는 것을 forwarding 이라고 한다
    
    return  render(request, 'index.html',{"message":msg})
  • mydjango 디렉토리에 templates 디렉토리 생성 하고 index.html 파일 작성


forwarding 과 redirect

  • 서버에서 처리가 끝난 후 클라이언트에게 데이터를 전송할 때 이동하는 방법
  • fowarding 은 작업의 흐름을 변경하지 않고 그대로 둔 상태에서 이동
    • 사용자의 요청 객체가 계속 유지가 된 상태로 작업을 진행
    • 새로고침 하게 되면 처리를 다시 수행
    • 검색 작업이나 단순한 페이지 이동은 fowarding 을 사용
    • 서버 - 클라이언트 불가능
  • redirect는 작업의 처리가 완료된 상태로 새로운 작업의 흐름을 만들어서 이동
    • 사용자의 요청 객체를 소멸시키고 새로 생성해서 새로운 작업을 생성
    • 새로고침을 하게 되면 결과만 다시 출력된다
    • 검색 이외의 작업은 무조건 redirect 임
    • 서버 - 클라이언트 가능

템플릿 엔진 문법

  • 데이터 출력 : {{데이터이름}}
    • 데이터가 객체 형태로 여러 개의 속성을 자기는 경우는 데이터이름.속성으로 접근 가능
  • 분기문
{% if 조건 %}
		처리할 내용
{% else %}
		처리할 내용
{% end if%}
def index(request):
    # 클라이언트에게 문자열 응답을 전송
    #return HttpResponse("Hello Django");

    msg = 'use first Template Engine'
    # template 디렉토리에 있는 index.html 파일로 출력하는데
    # 데이터를 message 라는 이름으로 전달
    # request 와 함께 전달해서 화면을 만드는 것을 forwarding 이라고 한다

    success = False
    name = "lee"
    return  render(request, 'index.html',{"message": msg,"success":success,"name":name})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>메인</title>
</head>
<body>
{{message}}<br />

{{name}}<br />
{{success}}<br />

{% if success == True %}
    성공<br/>
{% else %}
    실패<br/>
{% endif %}


{% if name is lee %}
    로그인<br/>
{% else %}
    {{name}} 님 안녕하세요<br/>
{% endif %}
</body>
</html>
  • 반복문
{% for 임시변수 in 리스트 %}
			처리할 내용
{% endfor %}
def index(request):
    # 클라이언트에게 문자열 응답을 전송
    #return HttpResponse("Hello Django");

    msg = 'use first Template Engine'
    # template 디렉토리에 있는 index.html 파일로 출력하는데
    # 데이터를 message 라는 이름으로 전달
    # request 와 함께 전달해서 화면을 만드는 것을 forwarding 이라고 한다

    success = False
    name = "lee"

    ar = ["Developer","Operator","DevOps","MLOps"]
    return  render(request, 'index.html',{"message": msg,"success":success,"name":name,"ar":ar})

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>메인</title>
</head>
<body>
{{message}}<br />

{{name}}<br />
{{success}}<br />

{% if success == True %}
    성공<br/>
{% else %}
    실패<br/>
{% endif %}


{% if name is lee %}
    로그인<br/>
{% else %}
    {{name}} 님 안녕하세요<br/>
{% endif %}


<ol>
    {% for job in ar %}
        <li>{{job}}</li>
    {% endfor %}
</ol>
</body>
</html>


model

  • Django 에서 데이터베이스 연동하는 부분을 model이 처리

  • ORM : 객체 지향 언어의 객체 와 관계형 데이터베이스(RDBMS)의 하나의 행을 1:1로 매칭시켜서 객체 지향 문법으로 데이터베이스를 사용하는 프레임 워크

    • 최근에 데이터베이스 연동을 위할 때 대부분 ORM 방식을 사용하고, ORM 방식은 대부분 In Memory DB 의 개념을 사용하고 데이터베이스 종류에 상관없이 동일한 방법으로 접근이 가능
  • models.py 파일에 클래스 형태로 데이터베이스 테이블과 연동할 클래스를 선언

    • 이 클래스는 django.db.models.Model 클래스의 파생 클래스
  • 연동할 테이블이 없으면 테이블을 자동 생성하고 Primary Key가 없으면 id를 자동으로 생성

  • 클래스 안에 static 필드를 선언하고 자료형 과 제약조건을 설정

  • 데이터 베이스 연결은 데이터베이스에 해당하는 라이브러리를 설치하고 settings.py 파일의 DATABASES 라는 변수에 접속 정보를 기재하면 됨

  • 접속 기재 방법은 https://docs.djangoproject.com/en/4.1/ref/settings/#databases

  • 설정한 내용을 반영

    • python manage.py makemigrations

    • python manage.py migrate

    • 만들어지는 테이블 이름은 앱이름_ModelClass 이름


MariaDB 연결을 위한 설정

  • DB에 접속해서 사용할 데이터 베이스 생성
  • 장고 프로젝트에서 pip install mysql-client
  • pip install mysql-client 가 오류날 경우
$ brew install mysql-client
$ echo 'export PATH="/usr/local/opt/mysql-client/bin:$PATH"' >> ~/.bash_profile
$ export PATH="/usr/local/opt/mysql-client/bin:$PATH"
$ pip install mysql-client

!! 참고 - mysql-client 를 설치했으나 없다고 오류를 뿜을 경우!!


models.py

  • mydjango의 models.py 파일에 테이블과 연결할 Model클래스 생성
from django.db import models

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)
  • DB 에 적용
python manage.py makemigrations
python manage.py migrate

  • DB에 아이템 넣기
insert into mydjango_item values(1, 'Lemon', 500, 'Vitamin-A', 'lemon.jpg'); 
insert into mydjango_item values(2, 'Orange', 1500, 'Vitamin-B', 'orange.jpg'); 
insert into mydjango_item values(3, 'Kiwi', 2000, 'Vitamin-C', 'kiwi.jpg'); 
insert into mydjango_item values(4, 'Grape', 1000, 'Vitamin-D', 'grape.jpg'); 
insert into mydjango_item values(5, 'Strawberry', 2000, 'Vitamin-E', 'strawberry.jpg'); 
insert into mydjango_item values(6, 'Mandarin', 300, 'Vitamin-F', 'mandarin.jpg'); 

commit;

select * from mydjango_item;

테이블의 전체 데이터를 읽어서 출력

  • 테이블의 데이터를 전부 가져오기
from django.shortcuts import render
from mydjango.models import Item
# Create your views here.

from django.http import HttpResponse

def index(request):
    print(Item) # 확인용
    data = Item.objects.all()
    print(data) # 확인용

    return render(request, 'index.html', {'data':data});
  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>목록 보기</title>
</head>
<body>
    <h2>상품 목록 화면</h2>
    <table border="1">
        <thead>
            <tr>
                <th>상품ID</th>
                <th>상품이름</th>
                <th>가격</th>
            </tr>
        </thead>
        <tbody>
            {% for item in data %}
                <tr>
                    <td>{{item.itemid}}</td>
                    <td>{{item.itemname}}</td>
                    <td>{{item.price}}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
</body>
</html>

테이블 상세보기

  • 목록보기에서 제목 등의 부분에 링크를 설정해서 링크를 누르면 데이터를 자세히 출력하는 형태로 많이 구현함

  • 제목을 클릭할 때 하나의 데이터를 찾을 수 있도록 기본키 값을 전달해야 한다.

  • 기본키를 가지고 데이터를 검색해서 출력한다.

  • 예전에는 데이터를 넘길 때 파라미터 방식을 많이 사용했는데 최근에는 URL에 포함시키는 형태를 많이 사용한다.

  • index.html 파일의 제목 출력 부분을 변경


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>목록 보기</title>
</head>
<body>
    <h2>상품 목록 화면</h2>
    <table border="1">
        <thead>
            <tr>
                <th>상품ID</th>
                <th>상품이름</th>
                <th>가격</th>
            </tr>
        </thead>
        <tbody>
            {% for item in data %}
                <tr>
                    <td>{{item.itemid}}</td>
                    <td><a href="/detail/{{item.itemid}}">{{item.itemname}}</td>
                    <td>{{item.price}}</td>
                </tr>
            {% endfor %}
        </tbody>v
    </table>
</body>
</html>

  • urls.py 파일에 위의 요청을 처리할 메서드를 연결
"""
from django.contrib import admin
from django.urls import path

# 실제 함수가 위치할 파일을 Import
from mydjango import views



urlpatterns = [
    path('admin/', admin.site.urls),
    # 기본 요청이 왔을 때 mydjango의 views.py 파일의 index 함수가 처리
    path("",views.index),
    # detail/숫자 요청이 오면 views.py 파일의 detail 함수가 처리
    path('detail/<int:itemid>',views.detail)

]
  • views.py 파일에 detail 함수 추가
from django.shortcuts import render
from mydjango.models import Item

# Create your views here.
from django.http import HttpResponse

# 클라이언트의 요청을 처리하는 함수
# 이 함수의 매개변수는 HttpRequest 타입인데
# 이 타입은 클라이언트의 정보를 가진 클래스

def index(request):
    # 클라이언트에게 문자열 응답을 전송
    #return HttpResponse("Hello Django");

    #msg = 'use first Template Engine'
    # template 디렉토리에 있는 index.html 파일로 출력하는데
    # 데이터를 message 라는 이름으로 전달
    # request 와 함께 전달해서 화면을 만드는 것을 forwarding 이라고 한다

    success = False
    name = "lee"
    data = Item.objects.all()
    print(data)
    ar = ["Developer","Operator","DevOps","MLOps"]
    return  render(request, 'index.html',{"data":data})

def detail(request,itemid):
    # itemid를 가진 데이터 찾아옴
    item = Item.objects.get(itemid=itemid)
    print(item)
    return render(request,'detail.html',{'item':item})
  • css, hs 또는 이미지 파일 처럼 내용이 변하지 않는 파일의 경로를 settings.py 파일에 작성
imports os # 임포트 해주고

STATIC_URL = 'static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, '../static')]
# 수정
  • img 파일들을 img 폴더에 넣기 - static 디렉토리 생성 - static디렉토리 아래에 img 디렉토리 삽입

  • templates 디렉토리에 detail.html 파일을 만들어 출력 내용을 생성
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>상품 상세보기</title>
</head>
<body>
  <h2>상품 상세 보기</h2>
  <table border="1">
    <tr>
        <td>상품 아이디</td>
        <td>{{item.itemid}}</td>
    </tr>
    <tr>
        <td>상품 이름</td>
        <td>{{item.itemname}}</td>
    </tr>
    <tr>
        <td>가격</td>
        <td>{{item.price}}</td>
    </tr>
    <tr>
        <td colspan="2">
            <img src="{% get_static_prefix %}img/{{item.pictureurl}}"/>
        </td>
    </tr>
  </table>
</body>
</html>

profile
무럭무럭 자라볼까

0개의 댓글