본문 바로가기
django

모델링과 마이그레이션 (1)

by shinminkyoung 2025. 1. 15.

 

외우기 보다는 참고의 내용으로 읽어보고 이러한 개념이 있다는 것을 알아두는 것에 의의를 두는 것을 추천한다. 

2.1 ER 모델링

2.1.1 주소

  • 주소 모델링 A: 주소를 문자열 형태의 데이터로 본 관점
  • from django.db import models ... address = models.CharField(max_length=256, blank=False)
  • 주소 모델링 B: 여러 문자열 형태의 데이터를 모아 만든 객체로 본 관점
  • from django.db import models class Address(models.Model): si = models.CharField(max_length=32) do = models.charField(max_length=32) gu = models.charField(max_length=32) detail = models.CharField( max_length=128, help_text="사용자가 입력한 정식 주소체계 이외 상세주소 ex: 서초 마제스타시티 타워2 15층 문앞", )

→ ER 모델링 단계에서 백엔드 개발자는 고객의 요구 사항 또는 기획자가 작성한 기획서를 살펴보고 여러 고민을 하고 판단해서 모델을 설계해야 한다.

<aside>

+) 장고에서의 DB 마이그레이션 수행 주체

DB 마이그레이션: ER 모델링과 같이 데이터베이스 구조에 변화를 주는 작업

DB 마이그레이션은 DBA (데이터베이스 관리자)의 영역

장고에서는 백엔드 개발자가 DB 마이그레이션을 주도할 수 있는 구조로 설계되어 있음

→ 장고 마이그레이션 모듈이 파이썬으로 SQL(DDL)을 제어할 수 있게 해주기 때문!

(최초 DB 마이그레이션 진행 이후에도 장고가 지속적으로 DB 마이그레이션을 관리할 수 있음)

(결론) 보통은 유 마이그레이션을 담당하는 주체는 DBA인 경우가 많지만, 이러한 장고의 특성으로 장고를 사용하여 개발하는 경우에는 DB 마이그레이션을 담당하는 주체가 백엔드 개발자가 될 수 있음

</aside>

2.2 장고의 모델

2.2.1 모델과 필드를 사용해야 하는 이유

  1. 파이썬 클래스 선언 예시
  2. from datetime import datetime class PythonModel: str_attr: str = "기본값" #최대 길이를 32자로 제한해주세요. int_attr: int = 0 bool_attr: bool = False datetime_attr: datetime = datetime.now()
  3. 데이터베이스에서의 테이블 생성 예시
  4. create table database_table( str_column varchar(32) not null default '', int_column integer notnull default 0, bool_column bool not null, datetime_column datetime not null default CURRENT_TIMESTAMP );

백엔드 개발ㄹ에서 모델링이 끝났다면 클래스 선언과 테이블을 생성하는 작업이 이루어져야 함

하지만, 위의 코드와 같이 각각 사용하는 언어가 다르기에 한 번에 관리하기 쉽지 않음

장고는, 2가지 작업을 한 번에 처리할 수 있도록 도와줌

여기서 사용되는 장고 객체가 Model과 Field

  • 모델과 필드를 사용해 한 번에 클래스 선언과 테이블 생성
    • IamDjangoModel이라는 이름의 클래스 선언과
    • I_am_django_model이라는 이름을 가진 테이블 생성 작업을 한 번에 처리 가능
    • 파이썬으로 클래스를 선언만 해줘도 데이터베이스에서 테이블을 설계할 수 있는 SQL로 컨버팅해주기 때문
    즉, 장고를 사용해서 코딩하면
  • 파이썬으로 작성해야 할 작업과 SQL로 작성해야 하는 작업을 한 번에 해결할 수 있음
  • from django.db import models class IamDjangoModel(models.Model): str_attr = models.CharField( max_length=32, help_text="최대 길이를 32자로 제한해주세요.", default="기본값", db_column="str_column" ) int_attr = models.IntegerField(default=0, db_column="int_column") bool_attr = models.BooleanField(default=False, db_column="bool_column) datetime_attr = models.DateTimeField(auto_now_add=True) class Meta: db_table = "i_am_django_model"

2.2.2 다양한 옵션

장고는 모델을 커스터마이징할 수 있는 다양한 옵션을 지원

Meta라는 Inner Class를 통해 장고의 모델을 제어할 수 있는 기능 제공

  1. abstract
  • 기본값: False
  • abstract가 True가 되면 해당 모델을 추상 모델로 취급= abstract = True인 모델은 데이터베이스에 테이블로 반영되지 않음
  • → DB 마이그레이션을 수행할 때 제외됨
  • 사용 예시
  • class Meta: abstract = True # abstract=True인 경우 db_table을 지정할 수 없습니다.
  • 만약, abstract=True인 테이블을 상속받는다면,
    • 이를 상속받은 모델만이 abstract=True의 테이블의 속성을 전부 받은 상태로 생성됨
  1. managed
  • 기본값: False
  • managed 값이 false이면 해당 모델이 DB 마이그레이션에서 아예 제외됨
  • = 해당 모델은 장고가 관리하지 않는 것
  • managed는 장고로 생성한 모델이 아니라,
  • 이미 생성된 데이터베이스 테이블에 매핑하고 싶거나 장고가 특정 테이블을 수정하는 것을 방지하고자 할 때 사용
    • 장고로 개발하기 전부터 존재했던 데이터 테이블을 사용하고 싶은 경우
    • DBA와 소통하면서 장고가 특정 테이블을 제어하지 못하게 막고 싶은 경우
    • 특정 테이블이 아닌 SELECT 쿼리를 모델에 매핑하는 경우 (주로 통계 쿼리)
  • 장고 모델은 데이터베이스 테이블에 매핑할 때 주로 사용되지만 반드시 모델과 테이블이 1:!로 매핑되는 것은 아님
  • 모델이 장고 매니저 객체를 사용해서 특정 SELECT 쿼리 또는 데이터베이스 뷰 테이블과도 매핑될 수 있음
  • (이후 자세히 다룸)
  1. proxy
  • 기본값: False
  • 하나의 테이블을 2개 이상의 모델로 나눠서 표현하고 싶을 때 사용
  • proxy 사용 예시
    • 실제 데이터베이스에 product라는 테이블만 존재하는 상황에서 product 테이블에 GroceryProduct, FurnitureProduct라는 2가지 proxy 모델을 새로 선언해서 매핑하는 것
    • product_type마다 사용되는 메서드가 다르기 때문에 모델을 분리해서 구현하는 것이 적절하다고 판단
  • class GroceryProduct(Product): # proxy 모델은 이런 식으로 반드시 구현이 완료된 Model(Product)을 상속받아야 한다. objects = GroceryProductManager() class Meta: proxy = True class FurnitureProductManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(product_type=Product.ProductType.FURNITURE) class FurnitureProduct(Product): objects = FurnitureProductManager() class Meta: proxy = True
  • 1개의 테이블을 2개 이상의 모델과 매핑하고 싶을 때 사용하는 것
  1. db_table
  • 기본값: f”{app_label}_{model_name}”
  • 장고는 개발자가 작성한 모델을 기반으로 테이블 이름을 지음 (JPA 이름 규칙과 비슷한 개념)
    • 장고 앱 이름 + 장고 모델 이름
  • 예시이렇게 지었으면
  •  shopping_mall_product 이렇게 지어짐 !
  • #shopping_mall.models.py class Product(models.Model): ...
  • 만약 수정하고 싶다면이렇게 수정하면but, 장고 앱의 이름을 포함하는 장고의 테이블 작명법은 좋은 방법이 아님.
  • so, 실무에서는 db_table 명을 항상 선언해줄 것을 권장함
  • → 테이블 이름은 product 가 됨
  • #shopping_mall.models.py class Product(models.Model): ... class Meta: db_table = "product"
  1. db_table_comment
  • SQL에는 comment라는 문법이 존재함
  • 테이블에 주석을 달아주는 역할 !
  • 만약, 장고 모델 또는 데이터베이스의 테이블을 설명하는 주석을 달고 싶다면 아래와 같이 사용
  • class Product(models.Model): store = models.ForeignKey( Store, on_delete=models.CASCADE, db_comment = "해당 상품을 가지고 있는 상점입니다.") name = models.CharField(db_comment="상품명") class Meta: db_table_comment = "상점의 상품입니다."
  1. get_latest_by
  • 기본값: pk
  • 장고 쿼리셋의 latest() 호출 시 사용됨
  • latest()를 호출할 때 가장 최근 값의 기준을 어떤 필드로 사용할 것인지를 명시하는 옵션
  1. ordering
  • 기본값: None
  • 장고 ORM으로 데이터 조회 시 정렬 방법을 설정할 때 사용
  • ordering에 아무 것도 설정되지 않으면 데이터베이스의 기본 정렬 값인 id(pk) 오름차순으로 정렬해서 데이터 조회

*장고에서는 id와 primary key를 동일한 값으로 사용

  1. indexes
  • 기본값: []
  • 데이터베이스에 DDL로 생성되어 반영되는 옵션
  • 인덱스
    • 특정 칼럼을 조건절로 사용할 때 SQL의 조회 성능을 훨씬 더 빠르게 해주는 데이터베이스 기능
    • but, 조회 성능이 빨라지는 만큼 생성 및 수정 속도가 느려짐
class Meta:
			indxes = (
					models.Index(fields=["created_at"], name="created_at_index"),
					models.Index(fields=["name", "product_type"], name="name_pt_composite_index"),
					
					# 각 database 별로 Index의 종류가 다양한데 postgres의 경우 django가 선택할 수 있도록 기능을 제공한다
  • created_at = models.DateTimeField(auto_now_add=True, db_index=True)와 같이 db_index=True를 설정하면 동일한 DB 인덱스가 생성됨
  • 복합 인덱스를 선언해야 한다면 indexes 옵션을 사용해야 함
  1. constraints
  • 기본값: []
  • 데이터베이스 수준에서 어떠한 조건을 제한하는 옵션
  • indexes처럼 DDL로 생성되어 반영됨
  • class Meta: constraints = ( models.CheckConstraint( check=models.Q(price__lte=100_000_000), name="check_unreasonanble_price", ), models.UniqueConstraint( fields=["store", "name", "product_type"], name="unique_in_store", ), )

'django' 카테고리의 다른 글

모델링과 마이그레이션 (3)  (5) 2025.01.17
모델링과 마이그레이션 (2)  (2) 2025.01.15
장고에 대하여  (4) 2025.01.07
3 - ORM과 Django Rest Framework (1)  (1) 2024.05.23
2 - Django Template과 Model  (4) 2024.05.22