💬 코드
serializers.py
class FriendSerializer(serializer.ModelSerializer):
when_request = serializers.SerializerMethodField()
def get_when_request(self, obj):
created_at = obj.created_at.date()
return created_at
위 코드에서 MethodField를 정의 하면, *get_필드네임 을 찾는다. 그렇기 때문에, 저런식으로 네이밍을 해주면 인자 값을 넘겨주지 않아도 사용 할 수 있다.
object는 메타클래스에서 사용하는 모델 클래스이다.
시리얼라이저는 결국, 파이썬에서 만든 클래스를 다른 어플리케이션에서 읽기 위함이다. 그렇기 때문에 웹에 보여지는 부분을 커스텀 한다고 생각 하면 편하다.
위 내용을 작성 하고 나서, 강의를 보고 나니 같은 얘기를 하고있다. 하지만, DRF를 그래도 어렵게 만드는건 시리얼라이저이니 공부가 필요한 객체 중 하나이다.
비즈니스 로직에 걸맞는 ER을 하고 나면, 그 관계도를 정의 하는 것이 모델링이다. 이 땐 테이블이 갖춰야 할필드를 명시 하는데 그 필드가 관계를 어떻게 나타내는지 정도만 필요할 뿐 모델링을 어렵게 느낄 필요가 없었다.
Model Viewset에 대해 자세히 알고 있지 않았지만, Django Rest Framework 핵심사항 강의를 보고 난 후 살짝 알게 된 계기가 되었다. 모델 뷰 셋은 프로젝트의 시작 단계에서 굉장히 빠른 빌드를 요구할 때 사용 하며, 그 이후 요구사항에 맞춰 Generic한 API view 들과 ModelViewSets을 사용 하여 커스터마이징 해 나가는 것이 중요하다. 그렇다면, 우리가 흔히 알고 있는 API View는? 이제 이 기능은 위의 제너릭한 뷰 들로 처리할 수 없는 기능을 구현 할 때 사용 하지만, 대부분 API View 까지 처리하지 않아도 모든 기능을 지원 받을 수 있다.
OneToOne Field와 ForeingKey는 인터넷에서 많이 떠돌았던 문제 중 하나였다. 사실, 1:N이냐 1:1이냐의 차이 이지만, 실제 사용 해보니 차이를 알기 어려웠다. 더 깊게 차이점을 공부하고 싶다면 더 검색하고 알아보면 되고, 이 문단에서 배운 점을 공유 하자면 OneToOne필드에서 관계를 짓고 있는 필드를 사용 하고 싶었다.
하지만, 접근을 잘못 했기 때문에 included 에러가 났었다.
유저: 회원가입시 간단한 정보를 담고 있음
유저 프로필 → 유저를 OneToOneField로 참조중
sender_name = serializers.EmailField(source="sender.name", read_only=True) included 에러 발생 이렇게, source 내부에 참조 되고 있는 필드 명(sender)에서 참조한 모델 객체의 필드 명을 불러온다.유저라는 시리얼라이저 생성, 유저 프로필 시리얼라이저에서 인스턴스화
💬 코드
serializers.py
class UserProfile(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = "__all__"
class UserProfileSerializer(serializers.ModelSerializer):
profile = UserProfile()
class Meta:
model = CustomUser
fields = ["name", "profile"]
views.pyclass ProfileViewSet(viewsets.ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
이렇게 하면, 유저 프로필에서는 모든 정보를 가져올 수 있고 커스텀 유저의 이름만 가져올 수 있다.
DRF 만세,,,✌️
👉 대충 이런 그림이 나온다
DRF 이미지

ModelViewSet에서 사용 되는 추가 기능 같은 존재다.
ModelViewSet은 흔히 알고 있듯이, 여러개의 Generic한 View의 집합인데, 그 기능 외에 추가적인 옵션이 더 필요할 때 사용했다.
예시

get object와 get queryset은 ModelViewSet을 작성 하다보면 필요한 요소 중 하나이다. 그 이유는 뷰셋은 상속 받은 클래스에 의해 기능이 구현 되도록 설계 되어 있기 때문에 우리가 알 수 없는 곳에서 에러가 발생 하고 그 에러를 트래킹 하면 결국 full system을 알아야만 뷰 셋을 이용 할 수 있게 되는데, 이러한 불편한 부분을 해소 하기 위해 많은 메서드들을 오버라이딩 한다. 그 중에 List와 Retreive, Update 상황에서 흔히 마주칠 수 있는 오버라이딩 방식을 공유한다.
우선, 나의 개인 프로젝트 중에서 유저의 마이페이지를 가지고 오고 싶었고 프로필이라는 ViewSet이 존재 했다. 하지만, 이 뷰셋은 타인의 프로필을 접근하는고 친구 요청을 보내고 하는 것은 자연스러웠다. 하지만, 내 프로필에 접근 하려면? 만일, retrieve를 건들었다면 타인의 프로필을 못 봤을 것이다.
그래서 고민 했던 점이 프로필에서 action을 써서 마이 페이지를 구성 할지, 새로운 APIView 클래스를 만들지 고민했고 무분별한 action 보다는 하나의 깔끔한 뷰가 나을 것 같다는 판단 하에 뷰를 만들었다.
우선 코드를 보기 전, 본론으로 돌아와 get object와 get queryset을 간단하게 설명하고 예제를 본다면 이해 하기 쉬울 것이다.
Retrieve, Update, Delete와 같이 pk가 요구 되는 detail 페이지의 기능을 구현 할 때 필터링 할 수 있는 오버라이딩 메소드이다.
👉 get_object 메서드는 단일 객체를 가져오는 역할을 수행한다. 일반적으로 get_queryset 메서드에서 반환된 QuerySet을 기반으로 조회하며, 주로 상세조회(detail) 기능에서 사용된다.
List와 같이 전체적인 데이터를 조회 할 때 사용 할 수 있고, objects.all()과 같이 전체 데이터를 조회 하는 것이 아닌, 필터링 또는 정렬 등 다양한 옵션을 사용 해서 리스트의 쿼리셋을 조율 할 때 사용한다.
👉 get_queryset: 이 메서드는 목록(list) 조회 시 사용되며, 특정 모델의 객체들을 가져오는 역할을 수행한다. 일반적으로 QuerySet을 반환하고, 이를 통해 필터링, 정렬 등의 추가 조작을 수행할 수 있다.
그럼, 메서드를 간단하게 파악 했다면 코드를 보고 다시 이해 해보자
class MyPageView(RetrieveUpdateAPIView):
"""마이 페이지 접근"""
model = UserProfile
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
에러를 직역 해보자면, 마이페이지 뷰는 URL의 pk값을 갖고 있어야 한다. URL을 수정 하거나, 룩업 필드를 올바르게 작성해라 라고 되어있다. lookup_field의 default는 pk이다. 하지만, 내가 원하는 것은 /api/mypage 했을 때 내 개인 페이지가 나왔으면 좋겠다고 요구사항을 만들었고, pk값은 보다시피 없다. 그리고 밑에 조금 내려가다 보면 Exception Location을 소개 해주는데, get_object 메서드 부분에서 에러가 났다는 것을 보여준다. 그렇다면 우리는 get_object를 오버라이딩 하면 이 문제를 해결 할 수 있을 것이다. 위 코드에서 get_object만 추가 한 형태def get_object(self):
queryset = self.get_queryset()
user_id = self.request.user.id
obj = get_object_or_404(queryset, profile_user_id=user_id)
return obj 
잘 나오는 것을 확인 할 수 있는데 get_object는 기본적으로 쿼리셋과 필터링 된 객체가 필요하다. 위에 간단하게 언급 했듯이 단일 페이지에 대해 접근 할 수 있는 메서드 라고 설명 했듯이, my_paged URL은 pk가 없으니 요청하는 유저의 id값을 받아 프로필에서 필터링 하여 오브젝트로 반환 하면 매끄러운 오버라이딩을 경험 할 수 있다.
get_queryset은 크게 에러를 범하고 하는 부분이 아니기 때문에 언급할 것은 없지만, 사용 예시를 들어보자면 이러한 형태이다.
사실 이 밑에 코드는 효율적이진 않기 때문에, 이럴 때 위 처럼 get_object를 쓰는게 더 올바르지 않았을까 라는 생각이든다.
def get_queryset(self):
"""요청 한 접근자의 프로필 정보 가져오기"""
if self.action == "retrieve":
user_id = self.kwargs["pk"]
return UserProfile.objects.filter(profile_user=user_id)
return UserProfile.objects.all() 하지만, 여기서 알아둘게 있다면 self.action은 현재 내가 접근하는 방식이다. Http 통신 방식에 매핑 되어 있는 뷰셋의 action이 있는데, 이 때 접근 방식을 볼 수 있다. 마지막 return 값을 어떻게 내야 하는지만 잘 보면 된다. 그저 필터링 한 쿼리셋 객체를 return 하고 있는 모습이다.