수학과의 좌충우돌 프로그래밍

[Django] 관계를 표현하는 모델 필드, ForeignKey,OneToOneField,ManyToManyField 본문

웹프로그래밍/Django

[Django] 관계를 표현하는 모델 필드, ForeignKey,OneToOneField,ManyToManyField

ssung.k 2019. 7. 20. 16:16

model 을 설계하는데 있어서 관계는 뺴놓을 수 없는 중요한 개념입니다. 각 모델 간에 여러 관계를 정의함으로서 많은 걸을 구현 할 수 있게 됩니다. 관계는 총 3가지가 있으며 이번에는 바로 그 관계에 대해서 알아보도록 하겠습니다.

ForeignKey

ForeignKey 는 1:N 관계를 의미합니다. 예를 들어 게시글과 댓글을 생각할 수 있습니다. 하나의 글에는 그 글에 해당하는 댓글이 여러 개 존재하게 되므로 ForeignKey 를 만족합니다.

  • django 에서의 사용 예시

    class Post(models.Model):
      # 생략
    class Comment(models.Model):
      post = models.ForeignKey(Post, on_delete=models.CASCADE)
    

    1:N 중에서 N 인 쪽에서 관계를 선언해주며, 두 개의 인자를 필요로 합니다. 하나는 대상이 되는 클래스, 다른 하나는 삭제 시 이슈에 대한 설정입니다.

  • on_delete 설정

    각각에 대한 설명은 1인 쪽의 데이터가 삭제 되었을 시, N 인 쪽의 데이터를 어떻게 처리할 지에 대한 설정입니다.

    • CASCADE : 이와 연결되어 있는 모든 N 쪽 데이터를 삭제합니다.
    • PROTECT : 1인 쪽의 데이터가 삭제가 되지 않도록 보호해줍니다.
    • SET_NULL : null 로 값을 대체하게 되어 필드에 null=True 옵션이 있어야만 가능합니다.
    • SET_DEFAULT : default 로 값을 대체하게 되어 필드에 default=True 옵션이 있어야만 가능합니다.
    • SET : 대체할 값이나 함수를 지정합니다.
    • DO_NOTHING : 아무 것도 하지 않지만 db 에서 오류가 발생할 수 있습니다.
  • 상대 모델에 접근하기

    # N -> 1
    comment.post
    
    # 1 -> N
    post.comment_set
    

    N인 쪽에서는 관계되어 있는 모델이 하나이므로 바로 접근이 가능하지만, 1인 쪽에서는 관계되어 있는 객체가 많기 때문에 set 을 통해서 접근할 수 있다.

  • limit_choices_to

    class Comment(models.Model):
      post = models.ForeignKey(
        Post,
        on_delete=models.CASCADE,
      	limit_choices_to = {'is_published': True},
      )
    

    다음과 같이 dictionary 형태로 1인 쪽의 필드와 필드값을 걸어줍니다. 이럴 경우, comment 입장에서 관계될 때 다음 필드와 필드값이 일치하는 Post 만 관계 지어질 수 있습니다.

    이는 ManyToMany 에서도 동일합니다.

 

OneToOneField

OneToOneField 는 1:1 관계를 의미합니다. 저는 이 관계를 django 에 기본적으로 정의되어 있는 User 모델과 이를 커스튬하여 새로 만드는 Profile 모델을 연결해줄 때 자주 사용합니다.

  • django 에서의 사용 예시

    class User(AbstractBaseUser):
      # 생략
    
    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
    

    위에서 말했던 예시에서 전체 코드의 일부입니다. 위 내용이 궁금하시면 이전 포스팅을 참고하시면 되겠습니다.

    해당 관계는 두 모델 중 어느 쪽에서 선언하여도 무방합니다.

  • 상대 모델에 접근하기

    user.profile
    
    profile.user
    

    각각에 대하여 대응되는 것이 유일하므로 바로 접근할 수 있습니다.

 

ManyToManyField

ManyToManyField 는 다대다 관계를 의미합니다. 예시로는 PostTag 를 생각할 수 있습니다.

  • django 에서의 사용 예시

    # 방법 1
    class Post(models.Model):
      tag = models.ManyToManyField('Tag',blank=True)
     
    class Tag(models.Model):
      # 생략
      
    # 방법 2
    class Post(models.Model):
    	# 생략
     
    class Tag(models.Model):
      post = models.ManyToManyField(post,blank=True)
    

    해당 관계는 두 모델 중 어느 쪽에서 선언하여도 무방합니다. 단 위에 있는 model 에서 아래 있는 model을 지정할 떄는 다음과 같이 문자열로서 표현을 합니다.

    blank=True 옵션을 걸어준 이유는 글을 쓸 경우 tag를 하나도 지정안할 수 도 있기 때문입니다.

  • 상대 모델에 접근하기
Comments