2 분 소요

RDBMS에서의 관계 예시

  • 1 : N 관계 -> models.ForeignKey로 표현
    • 1명의 유저(User)가 쓰는 다수의 포스팅(Post)
    • 1명의 유저(User)가 쓰는 다수의 댓글(Comment)
    • 1개의 포스팅(Post)에 다수의 댓글(Comment)
      • N 측에 외래키를 심는다!!
  • 1 : 1 관계 -> models.OneToOneField로 표현
    • 1명의 유저(User)는 1개의 프로필(Profile)
      • 둘다 되지만 profile측에 onetoonefield로 지정한다.
  • M : N 관계 -> models.ManyToManyField로 표현
    • 1개의 포스팅(Post)에는 다수의 태그(Tag)
      • 1개의 태그(Tag)에는 다수의 포스팅(Post)

ForeignKey

  • 1 : N 관계에서 N측에 명시
    • ex) Post:Comment, User:Post, User:Comment,
  • ForeignKey(to, on_delete)

    • 예시) models.ForeignKey(Post, on_delete=models.CASCADE)
    • to : 대상모델
      • 클래스를 직접 지정하거나,
      • 클래스명을 문자열로 지정. 자기 참조는 “self” 지정
    • on_delete : Record 삭제 시 Rule à
      • CASCADE : FK(외래키)로 참조하는 다른 모델의 Record도 삭제 (장고 1.X에서의 디폴트값)
      • PROTECT : ProtectedError (IntegrityError 상속) 를 발생시키며, 삭제 방지
      • SET_NULL : null로 대체. 필드에 null=True 옵션 필수.
      • SET_DEFAULT : 디폴트 값으로 대체. 필드에 디폴트값 지정 필수.
      • SET : 대체할 값이나 함수 지정. 함수의 경우 호출하여 리턴값을 사용.
      • DO_NOTHING : 어떠한 액션 X. DB에 따라 오류가 발생할 수도 있습니다
  • 외래키로 참조를 한다면?
class Comment(mdels.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    message = models.TextField()
    ...
  • 이러면 post_id 필드가 생성이 된다.
  • Post의 pk값을 통해 참조를 하는것이여서 post_id 필드가 생성이 되어 post_id로 접근을 해서 Post 모델에 참조한다.

  • user 모델을 쓸 때 프로젝트 만들자마자 settings로 가서
    • AUTH_USER_MODEL = “유저 모델을 쓸 앱이름.User” 쓰기!!
    • 안쓰면 default 값이 “auth.User”이다.
  • 그래서 User 모델을 대상모델로 지정하고 싶다면??

    • models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
  • comment에서 post 접근
  • 즉 N에서 1로 접근

image

  • Post에서 Comment 접근
  • 즉 1에서 N으로 접근

image

OneToOneField

  • 1 : 1 관계에서 어느 쪽이라도 가능
    • User:Profile
  • ForeignKey(unique=True)와 유사하지만, reverse 차이
    • User:Profile를 FK로 지정한다면 -> profile.user_set.first() -> user
    • User:Profile를 OneToOne 필드로 지정한다면 -> profile.user -> user
  • OneToOneField(to, on_delete) python # django/contrib/auth/models.py class User(AbstractBaseUser): ... # accounts/models.py class Profile(models.Model): author = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) https://docs.djangoproject.com/en/3.0/ref/models/fields/#onetoonefield

ManyToManyField

  • M : N 관계에서 어느 쪽이라도 필드 지정 가능
  • ManyToManyField(to, blank=False)

방법 1

class Post(models.Model):
    tag_set = models.ManyToManyField('Tag', blank=True)

class Article(models.Model):
    tag_set = models.ManyToManyField('Tag', blank=True)

class Tag(models.Model):
    name = models.CharField(max_length=100, unique=True)

방법 2

class Post(models.Model):
    ...

class Article(models.Model):
    ...

class Tag(models.Model):
    name = models.CharField(max_length=100, unique=True)
    post_set = models.ManyToManyField('Post', blank=True)
    article_set = models.ManyToManyField('Article',
blank=True)
  • 이 필드를 만들게 된다면 중간 모델이 생성되게 됨
  • 예를 들어 post와 tag가 manytomany 관계여서 한쪽에 이 필드를 만들었다면?
    • 앱이름_post_tag_set 이라는 모델이 생성됨

쉘에서 태그 추가, 제거 방법

  1. tag = Tag.objects.get(name=”장고”)
  2. post.tag_set.add(tag) // 생성
  3. post.tag_set.remove(tag) // 제거
    • 하나만 집어넣는것이 가능한데 여러개를 한번에 추가하고 싶다면??
    • 여러개가 담겨 있는 변수에 *를 붙여주면됨
    • ex)
      • tag_qs = Tag.objects.all()
      • post.tag_set.add(*tag_qs)

https://docs.djangoproject.com/en/2.1/ref/models/fields/#manytomanyfield

RDBMS지만, DB따라 NoSQL기능도 지원

  • ex) 하나의 Post 안에 다수의 댓글 저장 가능
  • djkoch/jsonfield
    • 대개의 DB엔진에서 사용 가능
    • TextField/CharField를 래핑
    • dict 등의 타입에 대한 저장을 직렬화하여 문자열로 저장
      • 내부 필드에 대해 쿼리 불가
  • django.contrib.postgres.fields.JSONField
    • 내부적으로 PostgreSQL의 jsonb 타입
    • 내부 필드에 대해 쿼리 지원
    • 예시
      • posts = models.JSONField(default=’{}’)
  • adamchainz/django-mysql
    • MySQL 5.7 이상에서 json 필드 지원

댓글남기기