태그 기능 만들다가 마주한 오류.
내가 만든 태그 기능은 한 작업물당 태그를 붙이는 방식이 아니라
filtering을 거쳐서 나온 목록들 여러개에 한번에 태그를 붙일 수 있는 기능이다.
그래서 view의 filtered_queryset에 바로 접근하기 위해 FilteredQuerySetMixin
이라는 class를 serializer에 override해 사용하고 있었다.
FilteredQuerySetMixin
이 하는 일은 오로지 view에서 filtered_queryset을 받아오고, 만약 데이터가 존재하지 않으면 처리할 수 있는 객체가 없다고 에러 메시지를 내뱉는 간단한 용도였다.
문제가 생긴 건 init의 view = kwargs['context']['view']
이 부분이었다.
def __init__(self, *args, **kwargs):
view = kwargs['context']['view']
self.filtered_queryset = view.filter_queryset(view.get_queryset())
super().__init__(*args, **kwargs)
이상하게도 자꾸 ‘view’를 찾을 수 없다고 Keyerror가 뜨는 것이다.
분명히 ViewSet에서 보내주는데 어째서 …?
디버깅해보니
init 에 요청이 들어오는 건 총 두 번.
첫 번째 요청에서는
정상적으로 ViewSet을 가져온다.
하지만 두 번째 요청에서는 ’view’를 가져오지 못한다.
그렇다면 두 번째 요청은 언제 들어오며 왜 들어오는가?
왜 두 번째 요청부터는 view를 받아오지 못하는가?
전에도 태그 적용 기능은 만든 적이 있지만
그때는 이 버그를 찾지 못했던 이유가
마침 그때는 리스트를 필터링할 때 ordering 필터를 사용하지 않았기 때문이다.
rest framework의 OrderingFilter를 사용할 때는 serializer를 통해 FilteredQuerySetMixin의 init을 호출한다. 두 번째 요청의 정체는 이거였다. 그 때는 view를 거치지 않기 때문에 당연히 kwargs['context']에는 ‘view’가 없으니 오류가 나는 것.
def __init__(self, *args, **kwargs):
try:
view = kwargs['context']['view']
self.filtered_queryset = view.filter_queryset(view.get_queryset())
except KeyError:
self.filtered_queryset = None
super().__init__(*args, **kwargs)
이렇게 try except로 감싸주면 해결.
사실 해결방법 자체는 말도 안 되게 쉽지만
왜 이런 오류가 일어나는지 정확한 원인 찾기,
어떻게 해결하는 게 가장 옳은 방식일지 고민하기
요즘 이 두 가지를 많이 훈련중이다.
예전에는 오류 해결하기 급급했음...