00 Django란
- 웹 프레임워크 중 하나로, 웹 애플리케이션을 효율적으로 빠르게 개발하는 데 사용할 수 있는 소프트웨어
- 일반적인 웹 개발 업무에 즉시 사용할 수 있는 구조를 제공하여 몇 줄만으로 코드를 작성 가능
- Python 언어로 작성됨
01 제공하는 구조
- 사용자 인증, 콘텐츠 관리, 사이트 맵, RSS 피드
1. 사용자 인증
- 현대의 웹 사이트는 사용자를 인증하고 권한을 부여해야 함
- 인증은 사용자의 ID를 확인하고 권한 부여는 인증된 사용자가 사이트에서 수행할 수 있는 작업을 결정함
- Django는 다양한 용도로 인증을 관리 가능:
- 사용자 계정
- 사용자가 특정 웹 사이트 태스크를 수행할 수 있도록 허용하는 권한 및 ‘예 또는 아니요’ 플래그
- 유사한 권한을 가진 여러 사용자 계정의 그룹
- 쿠키 기반 사용자 세션
- 구성 가능한 암호 해싱 시스템과 양식 및 보기의 콘텐츠를 제한하는 도구를 제공
02 DBMS와 연동
- 연동되는 DBMS: PostgreSQL, MariaDB, MySQL, Oracle, SQLite
0. 참조
1. ORM이란
- Object-Relational Mapping의 약자
1) 정의 및 기능
- 객체(Object)와 관계형 데이터베이스(Relational DB)를 연결해줌
- ORM 이용시 SQL을 적지 않고도 프로그래밍 언어로 DML을 수행 가능
- 객체지향적인 코드를 통해 데이터를 다루기 때문에 코드 가독성이 높고, 이는 생산성을 높여줌
- lazy-loading이나 caching 같은 기능을 통해 불필요한 쿼리를 줄여줌
- Django는 ORM을 지원
2) Django ORM 개요
- 하나의 Model Class는 하나의 DB Table에 해당
- 모델 클래스를 통해 생성한 하나의 Instance는 하나의 Table Record에 해당
- SQL은 기본적으로 Table 단위로 쿼리하기에 Django에서 역시 Model Class 단위로 쿼리함
3) 용어
- QuerySet (쿼리셋)
- Python에서 실행한 SQL 쿼리에 대한 결과/반환값
- iterable한 객체
4) Django의 ORM 문법
- 클래스부터 시작 (SQL의 FROM절을 적는 것과 같음)
-
>>> User
-
- DB에서 데이터 읽어오기
- DB에서 데이터를 읽어오기 위해서 Manager를 통해 QuerySet을 만들어야 함
- User라는 모델 클래스의 objects라는 attribute가 Django ORM Manager에 해당
-
>>> User.objects
-
>>> manager = User.objects >>> manager # 결과값 <django.db.models.manager.Manager object at 0x7fe8d3b90668> >>> type(queryset) # 결과값 <class 'django.db.models.manager.Manager'>
- Django의 모든 모델 클래스는 기본적으로 objects라는 이름의 Manager를 갖고 있음
- Django의 ORM Manager는 모델과 DB 사이의 인터페이스
- Manager가 있기 때문에 추가적인 기능 (예: 특정 조건의 쿼리 재사용 등) 활용 가능
-
- Manager에 쿼리하는 데이터에 대한 조건 추가시 (예: 클래스명.objects.조건()) QuerySet 완성
- 조건 (함수) 종류
- all() 메소드: Table의 모든 레코드 반환
-
>>> User.objects.all() >>> queryset = User.objects.all() >>> type(queryset) # 결과값 <class 'django.db.models.query.QuerySet'>
- 위의 QuerySet (User.objects.all()) 은 아래의 SQL을 만들어냄
-
SELECT * FROM User
-
- filter() 메소드: SQL의 WHERE 절
-
>>> User.objects.filter(is_active=True)
-
SELECT * FROM User WHERE is_active = 1
-
- count() 메소드: 레코드 세는 기능
-
>>> User.objects.count() 3
-
SELECT COUNT(*) FROM User
-
- aggregate(집계함수('컬럼명')) 메소드: 집계함수 - SUM, COUNT, AVG, MIN, MAX 등
- 여러 레코드로부터 하나의 결과값 반환
- Null 값 주의
- 특정 컬럼을 기준으로 집계시 해당 컬럼이 NULL 값을 갖는 레코드는 집계에서 제외
- Count 함수 경우, 특정 컬럼 대신 *를 인자로 전달시 모든 레코드의 개수를 셈
- Count 함수
-
>>> from django.db.models import Count >>> User.objects.aggregate(Count('id')) {"id__count": 3}
- __count는 Django에 의해 기본으로 추가되는 이름
-
SELECT COUNT(id) AS id__count FROM User
- alias 추가하여 집계 결과의 이름 지정 가
-
>>> User.objects.aggregate(count=Count('id')) {"count": 3}
-
SELECT COUNT(id) AS count FROM User
-
- Avg 함수
-
>>> from django.db.models import Avg >>> Goods.object.aggregate(Avg('price')) {'prive__avg': 15000}
-
SELECT AVG(price) FROM Goods
-
- all() 메소드: Table의 모든 레코드 반환
- SQL & Execution Plan
- 반환값을 변수에 할당
-
>>> queryset = User.objects.all()
-
- QuerySet이 생성한 SQL쿼리 확인
-
>>> print(queryset.query) # 결과값 SELECT * FROM User >>> str(queryset.query) # 결과값 'SELECT * FROM User'
-
- sqlparse 활용하여 SQL 쿼리를 보기 좋게 출력
-
>>> import sqlparse >>> query = str(queryset.query) >>> print(sqlparse.format(query, reindent=True)) # 결과값 예) SELECT "DCVBridge_server"."hostname", "DCVBridge_server"."status", "DCVBridge_server"."core", "DCVBridge_server"."session_count", "DCVBridge_server"."update_date" FROM "DCVBridge_server"
-
- SQL 실행 계획 확인
-
>>> print(queryset.explain()) # 결과값 예시 1 SIMPLE User None ALL None None None None 1 100.0 Using filesort # 결과값 예시 Seq Scan on "DCVBridge_server" (cost=0.00..1.02 rows=2 width=27)
- 실행 계획은 쿼리의 성능 분석을 위해 반드시 확인해야 함
-
- 반환값을 변수에 할당
1. PostgreSQL
03 Django 사용하기
0. 참조
- https://076923.github.io/posts/Python-Django-9/#django-migration
- https://hub1234.tistory.com/26#google_vignette
1. Django 설치하기
1) 리눅스 환경
1> Python 및 pip 설치
- Django는 Python으로 개발된 웹 프레임워크이므로, Python이 설치되어 있어야 함
- 만약 Python이 설치되지 않았다면, 아래 명령어로 설치:
# Python 설치 (Ubuntu/Debian 계열)
sudo apt update
sudo apt install python3 python3-pip
# Python 버전 확인
python3 --version
2> 가상환경 생성 (옵션)
- 가상환경을 사용 시 프로젝트마다 독립된 Python 환경을 설정할 수 있어 패키지 관리가 용이하여 권장!
# 가상환경 생성 (myenv라는 이름의 가상화 환경 생성)
python3 -m venv myenv
# 가상환경 활성화
source myenv/bin/activate
. myenv/bin/activate
- 가상환경을 활성화하면 (myenv)와 같은 프롬프트가 보일 것
- 예시:
(myenv) [root@dya-si3 venv]#
3> Django 설치
- pip 명령어 사용하여 Django 설치
- 설치가 완료되면 django-admin 명령어 사용 가능!
pip install django
- 이왕 pip upgrade도 해주기
2. Django 프로젝트 생성하기
- django-admin 명령어로 새 Django 프로젝트를 생성
- myproject 디렉토리 안에 manage.py와 myproject라는 서브 디렉토리가 생성됨
# 새 Django 프로젝트 생성 (myproject는 프로젝트 이름)
django-admin startproject myproject
# 생성된 프로젝트 디렉토리로 이동
cd myproject
- 예시: (frontend_bi라는 프로젝트 생성)
3. Django 프로젝트 생성하기
- 프로젝트가 제대로 생성되었는지 확인하기 위해 개발 서버를 실행해보기
# 개발 서버 실행
python manage.py runserver
# 포트 지정 (기본값 = 8000)
python manage.py runserver 8003
- 브라우저에서 http://127.0.0.1:8000/ (포트 지정했을 경우 해당 포트)에 접속하면 Django의 기본 환영 페이지가 표시될 것!
4. Django 애플리케이션 생성하기
- myapp이라는 이름의 애플리케이션 디렉토리 생성
python manage.py startapp myapp
5. 데이터베이스 마이그레이션
- Django는 기본적으로 SQLite를 데이터베이스로 사용함
- 데이터베이스를 설정하려면 마이그레이션을 적용해야 함
python manage.py migrate
6. 슈퍼유저 생성하기
- Django 관리자 페이지를 사용하려면 슈퍼유저를 생성해야 함!
ython manage.py createsuperuser
04 주요 개념
1. Migrations
- Migration: DB의 Schema를 관리하기 위한 방법
- Schema: DB에서 자료의 구조, 자료 간의 관계 등을 기술한 것
- DB에서는 스키마를 비롯해 테이블, 필드 등의 변경이 발생했을 때 지정된 DB에 적용하는 과정을 의미
- model.py에는 모델이 정의만 되어있을 뿐, 이 자체로는 데이터베이스를 생성하고 적용하지 않음
- Migration을 통해 DB를 생성하고 모델의 생성, 변경, 삭제 등에 따라 작업 내역 관리 및 DB 업데이트 가능
1) 기본 Migration
- 실행:
python3.6 manage.py migrate
- 결과:
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
- python3.6 manage.py migrate으로 현재 프로젝트의 마이그레이션을 진행
- Migration 진행시, Django 프로젝트에서 사용하는 11개의 기본 테이블이 생성됨
- sqlite3 데이터베이스의 경우 Migration 진행시 생성되는 테이블은 다음과 같음:
- auth_group, auth_group_permissions, auth_permission, auth_user, auth_user_groups, auth_user_user_permissions, django_admin_log, django_content_type, django_migrations, django_session, sqlite_sequence
2) Migration 상태 확인
- 실행:
python3.6 manage.py showmigrations
- 결과:
admin
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
first_app
(no migrations)
sessions
[X] 0001_initial
- python3.6 manage.py showmigrations 명령어로 현재 Migration 상태 확인
- 기본적인 Migration으로 11개의 테이블이 생성되었지만, 모델(model.py)에서 생성한 테이블을 생성되지 않은 것을 확인
- 이제, 애플리케이션(앱)에서 생성한 모델에 대해 Migration을 적용할 것
3) 애플리케이션 Migration
- 실행:
python3.6 manage.py makemigrations first_app
- 결과:
Migrations for 'first_app':
first_app\migrations\0001_initial.py
- Create model UserModel
- python3.6 manage.py makemigrations [앱 이름]으로 모델에서 생성한 사항이나, 변경 사항된 사항을 감지하여 파일로 생성
- 단순하게 마이그레이션을 진행할 구조를 생성하는 것이므로, 적용은 되지는 않음
- 다시 python3.6 manage.py showmigrations 명령어를 통해 마이그레이션 상태를 확인할 경우, 다음과 같이 표시됨 (주의: 데이터베이스 종류에 따라 다른 SQL이 생성됨)
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
first_app
[ ] 0001_initial
sessions
[X] 0001_initial
- first_app에서 (no migrations)으로 표시되던 항목이 [ ] 0001_initial로 표시되는 것 확인 가능
- 이 변경사항에 대해 마이그레이션 진행
python3.6 manage.py migrate first_app
- 결과:
Operations to perform:
Apply all migrations: first_app
Running migrations:
Applying first_app.0001_initial... OK
- 결과에서 확인할 수 있듯이, first_app 앱에 대한 마이그레이션이 적용됨
- 다시 python3.6 manage.py showmigrations 명령어를 통해 마이그레이션 상태를 확인할 경우, 다음과 같이 표시
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
first_app
[X] 0001_initial
sessions
[X] 0001_initial
- first_app의 0001_initial이 적용된 것을 확인 가능
- python3.6 manage.py migrate first_app 명령어는 현재 적용되지 않은 Migration을 적용
- Migration이 정상적으로 적용될 경우, [앱_클래스명]의 형태로 테이블이 생성됨
- 예제를 기준으로 테이블의 이름을 확인한다면, first_app_usermodel 테이블이 생성됨
- 정상적으로 Migration이 완료되었다면, 프로젝트 실행 가능
4) 주의사항
- Migration 적용 후 모델(model.py) 수정시 다음과 같이 Migration 다시 적용 필수 (특정 앱에 대해 Migration 파일을 생성 후, 모든 변경사항을 적용하는 것)
-
python3.6 manage.py makemigrations [앱 이름] python3.6 manage.py migrate [앱 이름]
-
- Model Migration 진행시, 경고 문구가 발생한다면 필수 필드가 생성되었지만 기본값이 할당되어 있지 않아서 발생하는 문제
- 임의의 값을 모두 채워주거나 취소하여 건너 뛰기 가능
- 단, 임의의 값으로 채울 때 올바르지 않은 값을 채운다면 치명적인 오류 발생 가능
- Migration이 정상적으로 적용되었을 경우 다음과 같은 파일 구조를 갖음
-
[현재 프로젝트]/ > 📁 [장고 프로젝트 이름] ⬇ 📁 [장고 앱 이름] > 📁 __pycache__ ⬇ 📁 migrations > 📁 __pycache__ 🖹 __init__.py 🖹 0001_initial.py 🖹 __init__.py 🖹 admin.py 🖹 apps.py 🖹 models.py 🖹 serializers.py 🖹 tests.py 🖹 urls.py 🖹 view.py 🖹 db.sqlite3 🖹 manage.py
-
- Migration은 한 명만 진행하는 것이 좋음 (여러 명이 작업하는 경우 DB가 꼬일 수 있음)
- Migration은 DB Schema에 변화를 발생시키지 않더라도 수행하는 것 권장
- Migration은 모델의 변경 내역을 누적하는 역할을 하며, 적용된 Migration 파일은 제거하면 안됨
- Migration을 취소하거나 돌아가야하는 경우 다음과 같이 실행
-
python3.6 manage.py migrate [앱 이름] 0001_initial
- 위의 명령어를 실행할 경우 0001_initial의 상태로 되돌아감
- 현재 Migration이 적용된 상태가
- 0001_initial 이전일 경우: 정방향(forward)으로 Migration이 진행됨
- 0001_initial 이후일 경우: 순차적으로 지정된 Migration까지 역방향(backward)으로 Migration이 진행됨
-
- Migration을 초기화 해야하는 경우 다음과 같이 실행
-
python3.6 manage.py migrate [앱 이름] zero
- 현재 앱에 적용된 모든 Migration을 삭제함
- no such column 오류 발생시 Migration이 진행되지 않았다는 의미
- Migration은 디펜던시(dependencies) 순서에 의해 진행됨
-
5) DB 완전 초기화
- DB 삭제 및 완전 처음의 상태로 돌아가기 위해서는 다음과 같은 파일을 제거시 가능
-
[현재 프로젝트]/ ⬇ 📁 [장고 프로젝트 이름] > 📁 __pycache__ ⬇ 📁 [장고 앱 이름] > 📁 __pycache__ ⬇ 📁 migrations > 📁 __pycache__ 🖹 0001_initial.py 🖹 db.sqlite3
- 위 구조에서 [장고 프로젝트 이름]/__pycache__, [장고 앱 이름]/__pycache__, [장고 앱 이름]/migrations/__pycache__, [장고 앱 이름]/migrations/0001_initial.py, db.sqlite3을 삭제
- 모든 캐시 파일(__pycache__), 마이그레이션 내역(0001_initial.py), 데이터베이스(db.sqlite3)를 삭제한다면 초기 상태로 돌아가기 가능
- 위와 같은 파일을 제거할 경우, 기본 Migration부터 다시 진행해야 함
-
2. Serialization
- Serialization(직렬화): 메모리를 디스크에 저장하거나 네트워크 통신에 사용하기 위한 형식으로 변환하는 것
- 즉 QuerySet 등의 complex type을 JSON, XML 등의 content type으로 변환시키는 것
- Desrialization(역직렬화): 그 반대로 디스크에 저장한 데이터를 읽거나, 네트워크 통신으로 받은 데이터를 메모리에 쓸 수 있도록 다시 변환하는 것
- Django의 Serializer
- Django에서 사용하는 파이썬 객체, QuerySet 같은 복잡한 객체 (모델 인스턴스)들을 REST API에서 사용할 JSON 과 같은 형태로 변환해주는 어댑터 역할
참조:
- https://aws.amazon.com/ko/what-is/django/
- https://docs.djangoproject.com/en/4.2/ref/databases/
- https://www.qu3vipon.com/django-orm
- https://076923.github.io/posts/Python-Django-9/#django-migration
- https://hub1234.tistory.com/26#google_vignette
- https://www.incodom.kr/Django_ORM#h_32232b2c9daa072f5dbf7584fba696bf
'Web 개발 > Django' 카테고리의 다른 글
QuerySet API (쿼리셋 API) (0) | 2024.03.25 |
---|---|
Django의 values() vs values_list() (0) | 2024.03.25 |
Django Static 파일 관리하기 (image, JavaScript, CSS, etc.) (0) | 2024.03.20 |
Django urlpatterns 함수: path, re_path, include, register_converter, static (0) | 2024.03.20 |