본문 바로가기

web/Django_rest_framework

3 get detail 구현


앞써 /api/posts/ 를 통해 post의 데이터를 리턴하는 list endpoint를 구현하였습니다. 

이번에는 리스트가 아닌 하나의 객체를 리턴하는 detail endpoint 를 구현할 포스팅입니다. 


최종적으로 /api/posts/포스트아이디/ 를 통해서 데이터를 리턴하는 페이지를 구현할 것입니다. 


해당 포스팅의 모든 소스는 아래의 링크에서 다운 받을수 있습니다. 

https://github.com/uiandwe/django_rest_api/tree/8b876de0dbaf207ec351a64fcfaf4ee91cf445b6



1. 먼저 detail의 url를 보기 위한 표현 할 정보중 해당 id 를 표현하기 위해 시리얼라이져의filedls에 pk를 추가해 줍니다. 

    post/api/serializers.py


   pk 속성 추가

fields = [
'pk',
'title',
'content',
'created_at',
]



2. /api/posts/ 로 확인해 보면 pk와 해당 데이터가 추가된것을 확인할수 있습니다. 



3. detail 로직을 구현하기 입니다. 

    post/api/views.py 에 rest_framework.generics 의 RetrieveAPIView 를 추가 줍니다. 


    RetrieveAPIView는 오직 하나의 인스턴스만 리턴해 주는 API입니다. 


   (http://www.django-rest-framework.org/api-guide/generic-views/#retrieveapiview)


    그리고 PostDetailAPIView()를 추가해줍니다. 

from rest_framework.generics import ListAPIView, RetrieveAPIView

.....
class PostDetailAPIView(RetrieveAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer


4.  이제 detail 를 표현할 url를 지정해 줘야 겠죠?!


     post/api/urls.py 에 아래의 url를 추가해 줍니다. 

  

    이제 /api/posts/포스트 아이디/ 를 통해서 detail 로직이 구현되었습니다.

urlpatterns = [
.....
url(r'^(?P<pk>\d+)/$', PostDetailAPIView.as_view(), name='detail'),


]


5. 수정!! 

    앞써 작성한 코드중 url이 잘못된 곳이 있습니다.


    django_rest_api/urls.py에 api/posts/ 의 url에서 뒤의 $를 빼줘야 합니다. 

    $의 경우 해당 url의 끝을 의미 하기 때문에 위에서 구현한 /api/posts/포스트 아이디/ 가 작동하지 않기 때문이죠.


이전 소스

url(r'^api/posts/$', include("post.api.urls", namespace="posts-api"))


변경후 소스
url(r'^api/posts/', include("post.api.urls", namespace="posts-api"))



6. 이제 /api/posts/1/로 들어가 보시면!!

    아래와 같이 detail api가 작동하는것을 볼수 있습니다.


7. 여기서 끝!! 이라고 하면 무엇인가 찜찜할 것입니다. 

    사실 소스만 따라하다보면 놓칠수도 있는 부분인데요.


class PostDetailAPIView(RetrieveAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer


위의 함수에서 사실 pk를 받는 부분이 없습니다. 더군다나 Post.objects.all()를 통해서 모든 데이터를 가져왔는데 정확히 우리가 원하는 1번 데이터만을 리턴했습니다. 이상하죠?!


이부분은 RetrieveAPIView 클래스를 보게 되면 의문이 풀립니다. 

RetrieveAPIView는 아래와 같이 정의 되어 있습니다.

class RetrieveAPIView(mixins.RetrieveModelMixin,
GenericAPIView):
"""
Concrete view for retrieving a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)

RetrieveAPIView는 get을 실행하게 되고 get의 kwargs에 통해서 우리가 정의했던 변수들이 넘어가게 됩니다. 현재 정의된 변수는 pk가 되죠.


그래서 view 부분을 아래와 오버라이딩하면 넘어가는 pk값을 확인할수 있습니다. 


class PostDetailAPIView(RetrieveAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer

def get(self, request, *args, **kwargs):
print(kwargs)
return self.retrieve(request, *args, **kwargs)


그 다음에 retrieve에서 해당 pk값에 따른 인스턴스를 찾은후 리턴하게 되는거죠. 


아마도 앞으로 프로젝트를 수행하시다 보면 위와 같이 각 클래스를 오버라이딩 해야만 하는 날이 올수 있을수도 있습니다. (분명히 하게 됩니다. ㅎ) 공식 문서를 통해서 봐도 되자만 사용하는 클래스들을 한번씩 확인해 보시면 코드가 얼마나 깔끔한지 구경도 하는 재미도 있습니다. ㅎ




이번 포스팅은 여기까지 입니다.!!

다음번에는 해당 post 에 대한 update 와 delete를 구현해 보도록 하겠습니다. 



'web > Django_rest_framework' 카테고리의 다른 글

6 저장/수정시 유저 저장  (0) 2016.07.27
5. create  (0) 2016.07.27
4 update delete  (0) 2016.07.25
2. get method 구현  (0) 2016.07.25
1. django rest_framework 셋팅  (0) 2016.07.25