[TIL. 33]Django - Model작성하기 (관계설정,필드타입)

신지원·2021년 3월 28일
0
post-thumbnail
post-custom-banner

관계 설정

1:1 관계

class Drink(models.Model):
    korean_name = models.CharField(max_length=45)
    english_name = models.CharField(max_length=45)
    description = models.TextField()
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    allergies = models.ManyToManyField(Allergy)
    
class Nutrition(models.Model):
    one_serving_kcal = models.DecimalField(max_digits=6, decimal_places =2)
    sodium_mg = models.DecimalField(max_digits=6, decimal_places =2)
    saturated_fat_g = models.DecimalField(max_digits=6, decimal_places =2)
    drink = models.OneToOneField(
        Drink,
        on_delete=models.CASCADE,
        primary_key=True,
    )

1대 1은 다음과 같이 설정한다.

1대1 관계는 두 모델 중 어느 쪽에 선언해도 괜찮음.

위에 category = models.ForeignKey(Category, on_delete=models.CASCADE) 에서 보면 fk 로 category가 string 형태가 아닌 변수명으로 나왔는데 이런경우에는 위에 이미 선언이 되었을때고, string 형태로 사용하면 위에서 미리 class가 선언되지 않았을때도 사용이 가능하다.

1:N 관계

ForeignKey 사용

class Post(models.Model):

class Comment(models.Model):
	post = models.ForeignKey(post, on_delete=models.CASCADE)

1:n 관계중 N인 쪽에 관계를 선언해주기 위해서, ForeignKey를 넣어준다.

  • ForeignKey(first parameter, on_delete=)

    • first parameter: 연결대상이 될 모델 객체
    • on_delete (필수)
      1인쪽의 데이터가 삭제 되었을 시, N인 쪽의 데이터를 어떻게 처리할지에 대한 설정
      • CASCADE: 연결되어이 있는 모든 N쪽 데이터를 삭제 한다.
      • PROTECT: 1인쪽의 데이터가 삭제되지 않도록 보호한다.
      • SET_NULL : null 로 값을 대체하게 되어 필드에 null=True 옵션이 있어야만 가능
      • SET_DEFAULT : default 로 값을 대체하게 되어 필드에 default=True 옵션이 있어야만 가능
      • SET : 대체할 값이나 함수를 지정.
      • DO_NOTHING : 아무 것도 하지 않지만 db 에서 오류가 발생할 수 있음

M:M

안된다..!

다대다 관계를 설정해주면, 두 테이블의 관계를 표현해주기 위해서 참조 정보를 담은 새로운 테이블이 생성된다.

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

class Drink(models.Model):
    korean_name = models.CharField(max_length=45)
    english_name = models.CharField(max_length=45)
    description = models.TextField()
    category = models.ForeignKey('Category', on_delete=models.CASCADE)
    Allergies = models.ManyToManyField(Allergy)

이렇게 따로 새로운 테이블을 생성하지 않고 만들어도 밑에 사진 처럼 drink_allergy 라는 테이블이 만들어진걸 확인 할수는 있었지만..allery_drink에 데이터를 넣을 수가 없었다.
그냥 단지 allergy_drink를 찾을 수 없다는 말뿐....

  • 추가) 이때는 당연히 안넣어지고 단순히 add 만 사용할 수 있다.

그래서 찾은 새로운 방법!

M:M relationship

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

class Drink(models.Model):
    korean_name = models.CharField(max_length=45)
    english_name = models.CharField(max_length=45)
    description = models.TextField()
    category = models.ForeignKey('Category', on_delete=models.CASCADE)
    Allergies = models.ManyToManyField(Allergy, through = "Allergy_drink")

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

1) 따로 Allergy_drink(각각의 테이블을 참조하는 중개모델)을 생성.
2) 중개 테이블에 FK 설정해주기
3) 다대다 관계설정해준 필드에 through = '중개모델' 추가해주기

이렇게 중개 테이블(두관계를 표현하는 테이블)을 따로 생성해주면 추가적인 정보를 담은 피드들을 중개 테이블에 삽입도 가능하다.

1:N 관계에서만 N쪽에 관계를 설정해주는 것!
다른 관계들은 어느쪽에 설정해주던지 상관 없다.

+) 이름_set 이라고 나오면 역참조임.
이거는 더 공부해야됨...

모델작성

  1. 필드타입은 장고 공식 문서에서 찾아가면서 작성하면 됨.
    https://docs.djangoproject.com/en/1.11/ref/models/fields/#decimalfield
  1. 모델 작성할때 fk에 굳이 _id 붙여주지 않아도 알아서 생성된다.
class Images(models.Model):
    image_url = models.CharField(max_length=200)
    drink= models.ForeignKey(Drink, on_delete=models.CASCADE) # 이부분 FK인데 알아서 뒤에 _id 붙음 

    class Meta:
        db_table = 'images'

위에 있는 Meta는 테이블명을 지정해주기 위한거.
만약, meta 적용해주지 않으면 product_image 이런식으로 알아서 적용됨.

post-custom-banner

0개의 댓글