October
11th,
2017
ForeignKey.on_delete 옵션 은 1측의 Row가 삭제될 경우, N측의 Row의 처리에 대한 동작을 지정한다.
- CASECADE : 연결된 Row를 일괄 삭제 (디폴트 동작)
- PROTECT : ProtectedError 예외를 발생시키며, 삭제 방지
- SET_NULL : null=True 설정이 되어있을 때, 삭제되면 해당 필드를 null 설정
- SET_DEFAULT : 필드에 지정된 디폴트값으로 설정
- SET : 값이나 함수를 지정. 함수의 경우 호출결과값을 지정
보통 CASECADE를 DEFAULT값으로 사용한다.
ForeignKey에서 Related_name 지정의 필요성
Many-to-One 관계에서 1측에서 N측으로 접근 시의 속성명 : 모델명소문자_set
>>> post = Post.objects.first()
>>> print(Comments.objects.filter(post=post)) # 방법1
>>> porint(post.comment_set.alL()) # 방법2
<Query set [<Comment: Comment object>, <Comment: Comment object>]>
<Query set [<Comment: Comment object>, <Comment: Comment object>]>
만약 2개의 앱이 동일한 모델을 가지고 있다면?
blog앱과 shop앱이 있다고 해보자. 이 둘의 앱은 각각 Post모델을 가지고 있고 ForeignKey로 User모델과 연결되어있다. 어떡해야 할까?
방법1. 각각 다른 related_name을 설정한다.
두 모델 모두 related_name=’post_set’ 으로 동일한 이름을 가지게된다. 이 때 중복을 발생하지 않게하기 위해서
blog앱의 속한 Post모델 ForeignKey의 related_name옵션은 related_name = ‘blog_post_set’
shop앱의 속한 Post모델 ForeignKey의 related_name옵션은 related_name = ‘blog_post_set’
혹은
related_name=”%(app_label)s_%(class)s_related” 로 통일하는 방법도 있다.
방법2. related_name을 포기한다.
related_name=’+’ 옵션값으로 ‘+’을 주면
user.post_set.all() # 이렇게 접근하는 건 안된다. 대신
shop.models.Post.objects.filter(user=user) # 이런식으로 접근해야 한다.
Many-to-many 에서 원하는 쿼리셋을 관계에 추가하기
사전작업 : 관련 Object 획득
post = Post.objects.first()
tag1 = post.tag_set.all()[0]
tag2 = post.tag_set.all()[1]
tag3 = post.tag_set.all()[2]
tag_qs = post.tag_set.all()[:3]
관계에 추가
post.tag_set.add(tag1)
post.tag_set.add(tag1, tag2)
post.tag_set.add(tag1, tag2, tag3)
post.tag_set.add(*tag_qs)
관계에서 제거
post.tag_set.remove(tag1)
post.tag_set.remove(*tag_qs)