• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

CBV DetailView pk_url_kwarg 클래스변수 재정의

23.04.25 03:57 작성 23.04.25 06:24 수정 조회수 324

1

만약 urls.py 에서 URL Cpatured Valueuid라는 식별자로 받았으면

CBV DetailView 클래스의 pk_url_kwarg 클래스변수를 당연히 재정의 해줘야하는데

어떤식으로 하는지 궁금합니다.

아예 DetailView 클래스를 상속받아서 확장할때

클래스변수 model 이든 pk_url_kwargs 든 재정의 한다음

확장한 블라블라DetailView클래스 로 .as_view() 메서드 호출하면 될꺼같은건 알겠는데

커스텀클래스 만들지 않고 하는 방식이 있다면(?) 궁금합니다!

그리고 보통 실무적으로/관례적으로 어떤방식으로 쓰이고 강사님은 어떨때 어떤방법을 선호 하시는지 궁금하고 그 이유도 궁금합니다.

(100% 이방법이 옳다 이방법이 많이 쓰인다 라는게 없다는건 알지만 장고가 아직은 낯설어서 best practice를 알고싶어서 그렇습니다)

 


만약 아래 강의 슬라이드 코드를 기반으로 살펴보면

아래코드처럼 as_view 메서드 호출 할 때 인자로 넘겨주면 되는건가요?

그러면 as_view 메서드 부터 이후 로직에서 알아서 내부적으로 클래스변수에 setter 해주나요? (그런 로직이 있다면)

post_detail1 = DetailView.as_view(mode=Post, pk_url_kwarg='uid') 

답변 1

답변을 작성해보세요.

0

안녕하세요.

클래스를 상속받아서 재정의하는 것은 메서드를 따로 오버라이딩할 때 하구요. 설정만 변경할 때에는 .as_view 호출 시에 필요한 인자만 지정합니다.

.as_view 함수 호출 시에 키워드 인자로, 그 CBV에서 지원하는 모든 클래스 변수 설정을 재정의하실 수 있습니다. 그렇게 View 클래스가 구현되어있습니다.

장고의 CBV마다 클래스 변수로서 여러 기본 설정들이 있습니다. 아래의 SingleObjectMixin에서는 pk_url_kwarg 클래스 변수가 "pk"로 기본 설정되어있습니다.
https://github.com/django/django/blob/main/django/views/generic/detail.py#L18

DetailView는 SingleObjectMixin을 상속받고 있죠. post_detail 뷰에서 pk_url_kwarg 설정만 변경코자 할 때에는 아래와 같이 .as_view 호출 시에 pk_url_kwarg 키워드 인자를 지정해줍니다.

post_detail = DetailView.as_view(model=Post, pk_url_kwarg="uid")

1) .as_view 호출 시에 넘긴 키워드 인자는 initkwargs 사전에 담겨있고
관련코드 : https://github.com/django/django/blob/main/django/views/generic/base.py#L81

2) .as_view 호출 시에 view 이름의 함수를 동적으로 생성하고, 그 함수를 반환합니다.
관련코드 : https://github.com/django/django/blob/main/django/views/generic/base.py#L96

3) view 함수가 호출이 될 때에는, 해당 클래스의 생성자를 호출하면서 (인스턴스를 생성하며) 1) 단계의 initkwargs 인자를 넘겨줍니다.
관련코드 : https://github.com/django/django/blob/main/django/views/generic/base.py#L97

4) View 클래스의 생성자에서는 인자로 받은 키워드 인자를 setattr을 통해 instance variable로 모두 등록을 합니다.
관련코드 : https://github.com/django/django/blob/main/django/views/generic/base.py#L53

파이썬 클래스에서 인스턴스는 self를 통해 instance variable 및 class variable에 접근할 수 있습니다.
인스턴스 입장에서 .속성명 으로 접근하면, instance variable을 먼저 찾고 없으면 class variable을 찾고 없으면 AttributeError를 발생시킵니다.

아래의 클래스 A에서는 key1 은 class variable입니다. 그러니 debug 안에서 self.key1 은 class variable인 key1을 출력합니다.

image

아래의 클래스 B에서는 debug 시점에 key2 이름의 instance variable과 class variable이 모두 존재합니다.

그렇다면 self.key2 는 instance variable은 key2를 출력하게 됩니다.

image

그런데 ~ !!! SingleObjectMixin에서 pk_url_kwarg 설정은 쿼리셋에서 Primary Key로서 조회합니다.
uid 필드가 primary key가 아니라면, get_object 메서드는 원하시는 대로 동작하지 않을 것입니다.

SingleObjectMixin 클래스의 get_object는 pk와 slug 필드에 대한 구현만 있으므로,
uid 필드에 대해서 구현한다면 클래스를 상속받아 get_object 메서드를 오버라이딩하는 것이 보다 간결하고 명확한 구현일 듯 싶습니다.

저는 가급적 pk와 slug로 조회를 하는 편입니다.

화이팅입니다. :-)

질문내용 흐름을 깊고 상세히 알려주시고 유스케이스까지 알려주셔서 + 게다가 파이썬문법(놓치고있었습니다. 파이썬 클래스변수/인스턴스변수 참조 방식/우선순위) 까지 알려주셔서 완전히 이해했습니다.

감사합니다