<Django>models.py 작성

jm_yoon·2021년 1월 13일
1

210113 TIL

장고 프로젝트 시작전에 에이쿼리를 통해 각각의 테이블관계를 생각해본다.
aquery

  • one to one
  • one to many
  • many to many

one to many인 경우

예를들어 "메뉴"와 "카테고리"를 생각해 보면 메뉴는 한 메뉴당 여러개의 카테고리를 가지고있기 때문에 one to many의 관계이다.

class Menu(models.Model):
    name = models.CharField(max_length=20)

    class Meta:
        db_table = "menu"


class Category(models.Model):
    name = models.CharField(max_length=20)
    menu = models.ForeignKey('Menu', on_delete=models.CASCADE)
    카테고리는 메뉴id를 갖기때문에 메뉴의 포린키를 클래스에 써줘야함

    class Meta:
        db_table = "category"

ForeignKey에서 on_delete=models.CASCADEon_delete=models.SET_NULL은?

on_delete 옵션은 Django에서 모델을 구현할 때 데이터베이스 상에서 참조무결성을 유지하여 ForeignKeyField가 바라보는 값이 삭제될 때 해당 요소를 처리하는 방법을 지정해준다.
  • CASCADE : ForeignKeyField가 바라보는 값이 삭제될 때 ForeignKeyField를 포함하는 모델 인스턴스(row)도 삭제된다. 예를 들어 메뉴 값이 사라지면 그 메뉴의 ForeignKey를 가지고있는 카테고리도 없어지는 것
  • SET_NULL : ForeignKeyField가 바라보는 값이 삭제될 때 ForeignKeyField값을 null로 바꾼다. (null=True일 때만 가능) 예를 들어 메뉴 값이 사라지면 그 포린키를 가지고있는 카테고리는 null값으로 가지고있음
  • PROTECT : ForeignKeyField가 바라보는 값이 삭제될 때 삭제되지 않도록 protectedError를 발생시킨다.
  • SET_DEFAULT : ForeignKeyField가 바라보는 값이 삭제될 때 ForeignKeyField값을 default값으로 바꾼다.(default값이 있을 때만 가능)

many to many인 경우

예를들어 "음료"와 "알러지"관계를 생각해보면 음료는 여러개의 알러지를 가질 수 있고
각각의 알러지도 음료 여러개에 해당할 수 있다. 이런 경우에는 중간테이블이 필요하다.

    1. 중간테이블을 class로 따로 선언하거나
    1. manytomany필드를 사용하면 된다.
      - manytomany필드를 사용할 경우 django에서 자동으로 중간테이블이 형성된다.
      - manytomany관계의 테이블 중 하나의 테이블에 manytomany필드를 입력하면되는데 데이터를 자주 불러오는 곳에 입력하는 것이 좋다.
      중간테이블을

중간테이블 선언

# 중간테이블  class 선언시
class Drink(models.Model): 
    name = models.CharField(max_length=50)
    category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
    
    class Meta:
        db_table = "drinks"
        
class Allergy(models.Model):
    name = models.CharField(max_length=50)
    
    class Meta:
        db_table = "allergy"


class AllergyDrink(models.Model):
    allergy = models.ForeignKey('Allergy', on_delete=models.CASCAD)
    drink = models.ForeignKey('Drink', on_delete=models.CASCAD)

    class Meta:
        db_table = "allergydrink"

manytomany필드

세부공간유형 테이블과 세부공간 테이블이 있을 경우
한 공간은 여러 공간유형을 가질 수 있고 한가지의 공간유형도 여러 공간을 가질 수 있기 때문에 many to many에 해당한다. 범위를 따져본다면 공간유형안에 공간이 속하기 때문에

class DetailType(models.Model):
    name = models.CharField(max_length = 45)

    class Meta :
        db_table = 'types'
        
class DetailSpace(models.Model):
    space = models.ForeignKey('Space', on_delete = models.CASCADE)
    name = models.CharField(max_length = 45)
    information = models.CharField(max_length = 500)
    main_image = models.URLField()
    min_people = models.IntegerField()
    max_people = models.IntegerField()
    detail_types = models.ManyToManyField(Type, db_table = "detail_space_type")
    Facilities = models.ManyToManyField(Facility, db_table = "detail_space_types")

    class Meta : 
        db_table = 'detail_spaces'

세부공간 class안에 detail_types = models.ManyToManyField(Type, db_table = "detail_space_type")을 써줘야한다.
뒤에 db_tableclass meta : db_table와 같은 의미임(데이터베이스명을 지정할 수 있다.)
만약 없을 경우 장고에서 마음대로 지정하는 경우가 발생..detail_spaces_detail_types이런식으로 이름이 길어지기 때문에 지정해주는 것이 좋다.

one to many 관계선언 시 다른 class를 가지고올때? " "따옴표를 붙이고 안붙이고 차이는?

파일 시작할 때 import선언을 안할경우 ""따옴표를 붙어야한다.
import선언을 했을 경우 (예를들어 from user.models import User(user앱의 models.py파일안의 class User를 import한다는 뜻))따옴표 붙일 필요없음

class선언시 반복적인 요소가 존재할 때 매번 선언하지 말고 추상화를 적용하기

from django.db import models

class Question(models.Model):
    content      = models.CharField(max_length = 300)
    user         = models.ForeignKey("users.User", on_delete = models.CASCADE)
    space        = models.ForeignKey("spaces.Space", on_delete = models.CASCADE)
    created_at   = models.DateTimeField(auto_now_add = True)
    updated_at   = models.DateTimeField(auto_now = True)

위 코드에서

created_at   = models.DateTimeField(auto_now_add = True)
updated_at   = models.DateTimeField(auto_now = True)

시간기록 요소는 Question 클래스 뿐만아니라 다른 class에서도 반복적으로 쓰인다.
이런 경우 장고프로젝트 디렉토리안에 utils.py파일을 추가하여 시간기록요소를 클래스로 만들어 import할 경우 코드를 좀더 깔끔하게 작성할 수 있다.

# utils.py

class TimeStampModel(models.Model):
    created_at  = models.DateTimeField(auto_now_add = True)
    updated_at = models.DateTimeField(auto_now = True)
    
    class Meta:
        abstract = True

'abstract = True'라는 구문을 넣게 되면 이 모델은 데이터베이스 테이블을 만드는데 사용이 되지않고 다른 모델의 기본 클래스로 사용될 때 자식 클래스의 필드가 추가된다.

from django.db import models

from utils import TimeStampModel

class Question(TimeStampModel):
    content      = models.CharField(max_length = 300)
    user         = models.ForeignKey("users.User", on_delete = models.CASCADE)
    space        = models.ForeignKey("spaces.Space", on_delete = models.CASCADE)

이런식으로 수정이 가능하다.
즉, TimeStampModel 클래스가 데이터베이스 테이블에 적용되지 않으면서 Question모델은 created_at, updated_at을 포함하여 5개의 필드를 갖게된다.

profile
Hello!

0개의 댓글