get_object() 란?
간단하게 get_object()는 pk로 queryset을 필터링 하고, queryset 결과에서 object를 뽑아서 return 시켜주는 함수이다.
실제 코드는 class SingleObjectMixin(ContentMixin) 내에서 확인할 수 있다.
https://docs.djangoproject.com/en/3.2/ref/class-based-views/mixins-single-object/#singleobjectmixin
내부의 주석을 번역하면서 하나씩 살펴보기로 하자.
def get_object(self, queryset=None):
"""
view가 display 하고있는 object를 반환합니다.
URLconf에 `self.queryset` 과 `pk` 혹은 `slug` 인수가 필요합니다.
서브클래스는 이를 오버라이딩하여 object를 반환할 수 있습니다.
"""
# 제공된 경우, custom queryset을 사용합니다. 이것은 서브클래스를 위해 필요합니다.
# like DateDetailView
if queryset is None:
queryset = self.get_queryset()
# 다음으로, pk로 검색을 시도한다.
pk = self.kwargs.get(self.pk_url_kwarg)
slug = self.kwargs.get(self.slug_url_kwarg)
if pk is not None:
queryset = queryset.filter(pk=pk)
# 다음으로, slug로 검색을 시도한다.
if slug is not None and (pk is None or self.query_pk_and_slug):
slug_field = self.get_slug_field()
queryset = queryset.filter(**{slug_field: slug})
# 이들 중 어느것도 정의되지 않는다면, 에러를 발생시킨다.
if pk is None and slug is None:
raise AttributeError(
"Generic detail view %s must be called with either an object "
"pk or a slug in the URLconf." % self.__class__.__name__
)
try:
# 이제 필터링 된 queryset에서 object를 가져온다.
obj = queryset.get()
except queryset.model.DoesNotExist:
raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': queryset.model._meta.verbose_name})
return obj
우선 함수의 파라미터(인자)를 살펴보면 queryset을 받게 되어있다. 즉, queryset을 함수 호출시에 인수로 보내면 custom queryset을 이용할 수 있다. 인자를 받지 않을 경우 해당 object의 기본 queryset을 참조하게 되어있다.
다음으로, pk를 통해서 queryset을 filter 하게 된다. 이 또한 없을 경우에는 slug를 통해 filter를 시도하게 된다.
만약 이들 중 어느것도 정의되지 않았다면 AttributeError를 발생시키게 된다.
마지막으로, queryset에서 object를 .get()을 통해 추출하고 return 하면서 함수를 종료한다.
즉, pk 및 slug 필드로 object를 가져올 때 이용되는 함수이다.
하나의 의문점
앞서 얘기 했던 것과 거의 동일한 기능을 하는 코드가 존재한다.
'''
Leffe라는 클래스내라고 가정.
'''
# get_object() 이용
leffe = self.get_object()
# 기본 ORM 이용
leffe = Leffe.objects.get(pk=pk)
위의 두 코드는 같은 기능을 하는 코드이다. 구현하는 방식의 차이만 있을 뿐이다. 보통 get_object()의 경우 self.~~로 사용하는 경우가 많기에 self 와 찾고자 하는 class가 일치한다면 get_object()를 쓰고, 그 외의 경우라면 objects.get()을 쓰는 것이 좋다고 생각한다.
self를 잘 이용하는 것이 조금 더 객체지향스럽고, pythonic한 코드이지 않을까 한다.
공부하면서 정리한 내용이니 틀릴 수 있습니다. 댓글로 남겨주시면 감사하겠습니다.
'SW개발 > Django' 카테고리의 다른 글
[Django]silk로 프로파일링 하기 (0) | 2021.08.20 |
---|---|
[Django]setUp() vs setUpTestData() 차이점 (0) | 2021.08.16 |
[Django]GenericForeignKey, ContentType로 여러 모델과의 관계 맺기 (0) | 2021.08.06 |
[Django]Django REST Framework - Permissions (0) | 2021.07.21 |
[Django]Docker-compose로 Django 환경 구축하기 6 - Celery (0) | 2021.06.11 |