Hands on 장고-모델링과 마이그레이션

김의석 ·2024년 4월 6일
0

Django

목록 보기
22/39

ER(Entity Relation) 모델링

ER 모델링의 주요 구성 요소

  • 개체(Entity): 현실 세계에서 독립적으로 존재하는 것을 나타냅니다. 예를 들어, 학생, 교수, 과목 등이 개체가 될 수 있습니다.

  • 속성(Attribute): 개체의 특성이나 속성을 나타냅니다. 예를 들어, 학생 개체의 속성으로는 학번, 이름, 전공 등이 있을 수 있습니다.

  • 관계(Relationship): 개체들 간의 연관성이나 관계를 나타냅니다. 예를 들어, 학생과 과목 사이에는 '수강'이라는 관계가 있을 수 있습니다.

  • 참고링크:
    https://velog.io/@yohanblessyou/CS-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-4.-E-R-Model

장고와 ER 모델링

  • 백엔드 개발의 시작은 ER모델링
  • ER 모델링이 완성된 데이터베이스 테이블장고 모델에 매핑하거나 장고 ORM을 사용해서 새로운 ER 모델링을 진행하는 것이 백엔드 프로그래밍의 첫걸음
  • 장고는 최초 모델링이 진행행된 후에 추가되는 모델링 이력을 관리할 수 있는 모듈인 장고 마이그레이션을 제공한다.
  • ER 모델링 단계에서 백엔드 개발자는 고객의 요구사항 또는 기획자의 기획서를 참고하여 모델을 설계한다.

장고에서 ER 모델링의 예시

import django.db import models

adress = models.Charfiled(max_length=256, blank=False)
  • 주소를 하나의 문자열로 생각하고 모델링을 하는 경우
import django.db import models

class Aderess(models.Model):
	si = models.CharFiled(max_length=32)
    do = models.CharFiled(max_length=32)
  	gu = models.CharFiled(max_length=32)
    detail = models.CharFiled(max_length=32)
  • 주소를 좀 더 세분화해서 시, 도, 군 과 같은 여러 문자열 형태의 데이터를 모아 만든 객체로 생각하고 모델링하는 경우

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

  • ER 모델링 같이 데이터베이스 구조에 변화를 주는 작업인 DB 마이그레이션은 DBA의 영역이다.
  • 장고에서는 백엔드 개발자가 DB 마이그레이션을 주도할 수 있는 구조로 설계되어 있다.
    • 장고 마이그레이션 모듈이 파이썬으로 SQL을 제어할 수 있게 해줌.

장고의 모델

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

장고 모델의 다양한 옵션

  • 장고의 모델을 커스터마이징하는 다양한 옵션
    • 추후 프로젝트에 적용 시 기술 예정

장고의 필드

Primary Key

문자열 자료형 관련 필드

숫자 자료형 관련필드

날짜 자료형 관련 필드

파일 업로드 관련 필드

그 외 자료형 관련 필드

모델 간 매핑 필드

ForeginKey(1:N 관계 매핑)
class Member(models.Model):
    teacher = models.ForeignKey(
        to="Teacher",
        on_delete=models.CASCADE,
        related_name="members",
    )
  • to : 1에 해당하는 쪽에 to 옵션을 준다.
  • on_delete : 1에 해당하는 모델의 데이터가 삭제 되었을 때 N에 해당 하는 모델 데이터를 어떻게 해야 할지를 정하는 옵션
    • on_delete=models.CASCADE : 1에 해당하는 모델 데이터 삭제 시 N에 해당하는 모델 데이터도 삭제한다.
    • on_delete=models.SET_NULL : 1에 해당하는 모델 데이터 삭제 시 이와 매핑 되어 있는 N에 해당하는 모델 데이터를 null로 채운다. null= True 시 가능.
  • 가급적 문자열로 모델 클래스명을 매핑할 것. -> 순환 참조 에러 방지
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    books = models.ManyToManyField('Book', related_name='authors')

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

# 위 코드에서 Author 모델과 Book 모델은 서로를 참조하고 있습니다.
# Author 모델은 Book 모델을 ManyToManyField로 참조하고 있고
# Book 모델은 Author 모델을 ForeignKey로 참조하고 있습니다.

# 에러 발생
# django.core.exceptions.FieldError: Invalid field name for ForeignKey 'author' on model 'Book': a model cannot have a field with the name 'author'.
# 이 에러는 순환 참조로 인해 발생하는 것으로, Book 모델에 있는 author 필드와 Author 모델 자체가 충돌하는 문제입니다.
  • 원리

    • 데이터베이스 스키마 생성: 장고는 모델 정의를 바탕으로 데이터베이스 스키마를 생성.

    • Author 모델은 Author_books라는 별도의 연결 테이블을 생성하여 Book 모델과 관계를 정의.

    • Book 모델은 author_id라는 외래 키를 사용하여 Author 모델과 관계를 정의.

    • 순환 참조 문제: 위의 모델 정의에서 Author 모델의 books 필드와 Book 모델의 author 필드가 서로를 참조하고 있어, 데이터베이스 스키마 생성 과정에서 문제가 발생한다.

Book 모델의 author 필드가 Author 모델을 참조하려고 하면서 Author 모델의 books 필드와 충돌.

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField('Author', related_name='books')
  • 문자열로 모델 참조: models.ManyToManyField 및 models.ForeignKey에서 문자열로 모델을 참조하고 related_name='books'옵션을 추가 하여 순환 참조 문제를 해결
OneToOne(1:1 매핑)
class ParkingSpace(models.Model):
	
    employee = models.OneToOneField(
    to="Employee", null=True, on_delete=models.SET_NULL,
    )
  • 1명의 직원이 1개의 주차 공간을 배정 받는 경우
  • OneToOne은 ForeginKey를 상속받은 필드여서 관련 옵션을 전부 사용할 수 있다.
  • 데이터베이스 관점에서 OneToOne은 ForeginKey에 unique=True 옵션을 가진 것과 같다.
    • OneToOne를 ForeginKey로 대체하는 것은 바람직하지 않다.
      • 참고 모델의 객체를 가져오는데에 있어 비효율
        • Employee.name
        • Employee.name_set.all()[0] -> 비효율
ManyToMany(M:N 매핑)
class Product(models.Model):
	name = models.Charfiled(max_length='128', help_text='상품명')
    class Meta:
	    db_table = 'product'
        
class OrderedProduct(models.Model):
	"""주문된 상품들"""
    order = models.FreignKey(to='Order', on_delete=models.CASCADE)
    product = models.ForeignKey(to='Product', on_delete=models.CASCADE)
    count = models.IntegerFiled(help_text='주문한 해당 상품의 개수', default=1)

class Order(models.Model):
	# ...
    product_set = models.ManyToManyField(to='Product', through='OrderdProduct')
    class Meta:
    	db_table = 'orderz'
  

# help_text는 Django의 모델 필드에서 사용되는 옵션으로
# 관리자 페이지나 폼에서 해당 필드의 설명이나 도움말을 제공하는 데 사용

# through='OrderedProduct'은 Order 모델과 Product 모델 간의 ManyToMany 관계를 표현하는 데 
#OrderedProduct 모델을 중간 테이블로 사용한다는 것을 의미.

# through 옵션을 사용하면, Order 모델에서 products라는 필드를 통해 여러 상품을 주문할 수 있으며
# 중간 테이블인 OrderedProduct를 통해 주문한 각 상품의 개수(count)를 관리할 수 있습니다.
  • through : M:N 매핑은 구조상 매개 테이블이 생성 되어야만 한다.
    • 장고에서 중간 매개 테이블을 알아서 생성해준다.
    • 개발자가 정확히 명시하고 싶다면 through옵션을 사용.
    • 예시는 Order와 Product간 M:N 매핑에서는 '주문한 해당 상품의 개수'라는 개념을 표현하기 위해 직접 생성
    • trough= 를 선언하는 이유
      • 예측할수 없는 확장 가능성
      • 직관적이지 않은 테이블명
        장고가 직접 중간 매개 테이블을 생성할 경우 테이블명이 중복 될 수 있다.
      • 장고가 존재 여부를 알 수 없는 테이블
  • through= 를 선언하지 않고 migrate를 한 경우의 문제점과 해결
    • 결론 : ManyToManyField 사용 시 through= 미리 선언하여 중간 매개 테이블을 생성하자 그렇지 않으면 추후 migrate가 어려워질 수 있다!

Migration

profile
널리 이롭게

0개의 댓글