1명의 유저(User)가 쓰는 다수의 포스팅(Post)
1명의 유저(User)가 쓰는 다수의 댓글(Comment)
1개의 포스팅(Post)에 다수의 댓글(Comment)
1 : N 이면, N 측에 외래키를 심는다.
1명의 유저(User)는 1개의 프로필(Profile)
1개의 포스팅(Post)에는 다수의 태그(Tag)
1개의 태그(Tag)에는 다수의 포스팅(Post)
ex) Post : Comment, User : Post, User : Comment,
to : 대상모델
클래스를 직접 지정하거나,
클래스명을 문자열로 지정. 자기 참조는 “self” 지정
on_delete : Record 삭제 시 Rule → https://docs.djangoproject.com/en/2.1/ref/models/fields/#django.db.models.ForeignKey.on_delete
CASCADE : FK로 참조하는 다른 모델의 Record도 삭제 (장고 1.X에서의 디폴트값)
PROTECT : ProtectedError (IntegrityError 상속) 를 발생시키며, 삭제 방지
SET_NULL : null로 대체. 필드에 null = True 옵션 필수.
SET_DEFAULT : 디폴트 값으로 대체. 필드에 디폴트 값 지정 필수.
SET : 대체할 값이나 함수 지정. 함수의 경우 호출하여 리턴값을 사용
DO_NOTHING : 어떠한 액션 X. DB에 따라 오류가 발생할 수도 있다.
class Post(models.Model):
message = models.TextField()
photo = models.ImageField(blank = True, upload_to = 'instagram/post/%Y/%m/%d')
is_public = models.BooleanField(defualt = False, verbose_name = '공개여부')
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
def __str__(self):
return self.message
class Meta:
ordering = ['-id']
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete = models.CASCADE)
# post = models.ForeignKey('Post', on_delete = models.CASCADE)
# post = models.ForeignKey('instagram.Post', on_delete = models.CASCADE)
# 다 가능
message = models.TextField()
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
class Post(models.Model):
message = models.TextField()
photo = models.ImageField(blank = True, upload_to = 'instagram/post/%Y/%m/%d')
is_public = models.BooleanField(defualt = False, verbose_name = '공개여부')
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
def __str__(self):
return self.message
class Meta:
ordering = ['-id']
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete = models.CASCADE)
# post = models.ForeignKey('Post', on_delete = models.CASCADE)
# post = models.ForeignKey('instagram.Post', on_delete = models.CASCADE)
# 다 가능
message = models.TextField()
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
댓글 작성
쿼리셋 확인
>>> from instagram.models import Post, Comment
>>> comment = Comment.objects.first()
>>> comment
<Comment: Comment object (1)>
>>> Post.objects.get(pk=comment.post_id)
4
>>> comment.post
<Post: 네 번째 포스팅>
>>> post = Post.objects.first()
post
<Post: 네 번째 포스팅>
>>> comment.objects.filter(post_id=4)
<QuerySet [<Comment: Comment object (1)>, <Comment: Comment object (2)>]>
>>> comment.objects.filter(post__id=4)
<QuerySet [<Comment: Comment object (1)>, <Comment: Comment object (2)>]>
>>> comment.objects.filter(post=post)
<QuerySet [<Comment: Comment object (1)>, <Comment: Comment object (2)>]>
>>> post.comment_set.all()
<QuerySet [<Comment: Comment object (1)>, <Comment: Comment object (2)>]>
4번째 post의 댓글 얻어오는 방법
reverse 접근 시의 속성명 : 디폴트 → “모델명소문자_set”
Post 측에서는 Comment와 다르게 참조할 이름이 없다.
왜냐면 FK는 N에 해당하는 모델에 심어주기 때문이다.
그래서 이런 경우 1에 해당하는 Post 측에는 “모델명소문자_set” 이라는게 생긴다!
>>> from instagram.models import Post, Comment
>>> post = Post.objects.first()
blog앱 Post모델, author = FK(User)
shop앱 Post모델, author = FK(User)
User : Profile
User : Profile를 FK로 지정한다면 → profile.user_set.first() → user
만약 1 : N의 관계에서 1측인 User가 없다면 None 반환
User : Profile를 O2O로 지정한다면 → profile.user → user
만약 1 : 1의 관계에서 1측인 User가 없다면 DoesNotExist() 예외 발생
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete = models.CASCADE)
address = models.CharField(max_lenght = 100)
zipcode = models.CharField(max_lenght = 6)
reverse 접근 시의 속성명 : 디폴트 → 모델명소문자
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete = models.CASCADE)
address = models.CharField(max_lenght = 100)
zipcode = models.CharField(max_lenght = 6)
>>> from accounts.models import Profile
>>> from django.contrib.auth import get_user_model
>>> User = get_user_model()
>>> profile.user
>>> user.profile
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_lenght = 100, unique = True)
class Post(models.Model):
...
class Article(models.Model):
...
class Tag(models.Model):
name = models.CharField(max_lenght = 100, unique = True)
post_set= models.ManyToManyField('Post', blank = True)
article_set = models.ManyToManyField('Article', blank = True)
>>> from instagram.models import Post, Tag
>>> post = Post.objects.first()
>>> post.tag_set.all()
<QuerySet [<Tag: 파이썬>]>
>>> tag = Tag.objects.first()
>>> tag.post_set.all()
<QuerySet [<Post: 네 번째 포스팅>]>
>>> Tag.objects.create(name='추가태그')
>>> Tag.objects.all()
<QuerySet [<Tag: 파이썬>, <Tag: 추가태그>]>
>>> tag = Tag.objects.get(name='추가태그')
>>> post.tag_set.add(tag)
>>> post.tag_set.all()
<QuerySet [<Tag: 파이썬>, <Tag: 추가태그>]>