장고 매니저
매니저
[모델이름].objects.all() 에서 .objects를 매니저라고 한다.
매니저는 장고 모델과 데이터베이스를 연결해 주는 인터페이스이다.
매니저를 통해 모델에 대한 ORM 연산을 수행할 수 있고 베이스 또는 기본 쿼리셋이 숨어있다.
숨겨진 쿼리셋 안에는 모델에 해당하는 모든 오브젝트들이 있고 일반 쿼리셋처럼 사용할 수 없다.
for post in Post.objects:
이렇게 사용할 수 없고
for post in Post.objects.all():
이렇게 사용해야 한다.
그리고 매니저에 CRUD 연산을 하면 숨겨진 쿼리셋이 사용된다.
Post.objects.order_by()
이렇게 숨겨진 쿼리셋을 정렬해서 리턴해준다.
Post.obejcts.all().order_by()
그래서 이렇게 사용하지 않는다.
역관계
역관계는 관계를 정의하는 필드를 통해 연결된 오브젝트에 접근하는 것이다.
class Comment(models.Model):
content = models.TextField(max_length=500, blank=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
User는 comment.author로 접근이 가능하다.
외래키는 한 쪽에만 작성을 하므로 외래키를 작성한 Comment에서만 접근이 가능할 것 같지만 반대로 User모델에서도 Comment모델로 접근이 가능한데
장고는 자동으로 반대 방향으로 접근할 수 있게 역관계를 만들어 주기 때문이다.
user.comment_set으로 접근할 수 있다.
여기서 user.comment_set는 매니저다.
이렇게 접근한 댓글(comment)은 모든 댓글을 가지는 것이 아니라 user가 작성한 댓글만 가지고 있다.
역관계가 가리키는 오브젝트가 하나일 때는 [모델이름]으로 접근하고
여러개 일 때는 [모델이름]_set 으로 접근한다.
역관계의 이름을 변경하려면 related_name=”변경할 이름” 옵션을 주면 된다.
역관계가 필요없다면 related_name=”+” 를 주면 된다.
OneToOneField
class User(AbstractUser):
...
class Profile(models.Model):
user = models.OneToOneField(User, ...)
프로필을 가지고 있는 유저는 profile.user로 접근
유저의 프로필은 user.profile로 접근
여기서 user.profile은 매니저가 아닌 실제 오브젝트다.
그래서 user.profile.nickname 이런식으로 접근할 수 있다.
ManyToManyField
class User(AbstractUser):
...
following = models.ManyToManyField('self', ...)
유저가 팔로우 하는 유저들 user.following
유저를 팔로우 하고 있는 유저들 user.user_set
이렇게 여러 오브젝트를 가리킬 때 user.following은 매니저이다.
GenericForeignKey
GenericForeignKey는 자동으로 역관계를 만들어 주지 않는다.
from django.contrib.contenttypes.fields import GenericRelation
class Review(models.Model):
...
likes = GenericRelation('Like')
...
class Like(models.Model):
...
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
liked_object = GenericForeignKey()
GenericForeignKey에는 on_delete옵션을 사용할 수 없지만
제네릭 관계가 가리키는 모델에 GenericRelation필드를 추가하면 CASCADE같은 효과를 얻을 수 있다.
content_type과 object_id이름을 사용했기 때문에 역관계를 형성하는 모델 이름만 넘기면 된다. 다른 이름을 사용했다면 알려줘야 한다.
related_query_name
User.objects.filter(following__id=1)
이런식으로 필터를 할수 있다.
GenericForeignKey로는 필터를 할 수 없다.
다양한 종류의 오브젝트를 가리키기 때문에 어떤 종류의 오브젝트인지 알 수가 없다.
이럴 때는 related_query_name속성을 사용하면 된다.
class Comment(models.Model):
likes = GenericRelation('Like', related_query_name='comment')
Like.objects.filter(comment=comment)
이렇게 특정 Comment에 속해있는 Like오브젝트를 필터할 수 있다.
검색기능
Q오브젝트
여러 필터 조건들을 or 한다.
조건들을 and하려면
Post.objects.filter(user=user).filter(post=post)
Post.objects.filter(user=user, post=post)
이렇게 하면 된다.
조건들을 or하려면 Q오브젝트를 사용해야 한다.
Q오브젝트는 어떤 조건을 저장하는 오브젝트를 말한다.
from django.db.models import Q
q1 = Q(field1=val1)
q2 = Q(field2=val2)
[모델].objects.filter(q1 | q2)
[모델].objects.filter(Q(field3=val3) | Q(field4=val4))
이렇게 or할 수 있다.
Leave a comment