티스토리 뷰

Django

Relationships & Hyperlinked APIs

nickas 2019. 8. 29. 17:23

Creating an endpoint for the root of our API

# views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse


@api_view(['GET'])
def api_root(request, format=None):
    return Response({
        'users': reverse('user-list', request=request, format=format),
        'snippets': reverse('snippet-list', request=request, format=format)
    })
    
# urls.py
urlpatterns = [path('', views.api_root)]

Creating an endpoint for the highlighted snippets

두가지 형태의 HTML renderer가 있음

  • Templates를 사용
  • pre-rendered HTML
from rest_framework import renderers
from rest_framework.response import Response

class SnippetHighlight(generics.GenericAPIView):
    queryset = Snippet.objects.all()
    renderer_classes = [renderers.StaticHTMLRenderer]

    def get(self, request, *args, **kwargs):
        snippet = self.get_object()
        return Response(snippet.highlighted)
        
# urls.py
urlpatterns = [path('snippets/<int:pk>/highlight/', views.SnippetHighlight.as_view())]

Hyperlinking our API

entity들 사이의 relationship을 정의하는 것은 Web API를 디자인 할 때 가장 힘든 부분.

다음과 같이 많은 경우의 수가 있음.

  • Primary key를 사용
  • entity들 사이에 Hyperlinking을 사용
  • Using a unique identifying slug field on the related entity
  • Using the default string representation of the related entity
  • Nesting the related entity inside the parent representation
  • Some other custom representation

REST framework는 위의 모든 경우를 지원

여기선 hyperlinked 형태 사용(HyperlinkedModelSerializer)

 

HyperlinkedModelSerializer vs ModelSerializer

  • 기본적으로 id 필드를 포함하지 않음
  • url 필드를 포함
  • PrimaryKeyRelatedField 대신에 HyperlinkedRelatedField를 사용
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')
    highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')

    class Meta:
        model = Snippet
        fields = ['url', 'id', 'highlight', 'owner',
                  'title', 'code', 'linenos', 'language', 'style']


class UserSerializer(serializers.HyperlinkedModelSerializer):
    snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True)

    class Meta:
        model = User
        fields = ['url', 'id', 'username', 'snippets']

Making sure our URL patterns are named

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

# API endpoints
urlpatterns = format_suffix_patterns([
    path('', views.api_root),
    path('snippets/',
        views.SnippetList.as_view(),
        name='snippet-list'),
    path('snippets/<int:pk>/',
        views.SnippetDetail.as_view(),
        name='snippet-detail'),
    path('snippets/<int:pk>/highlight/',
        views.SnippetHighlight.as_view(),
        name='snippet-highlight'),
    path('users/',
        views.UserList.as_view(),
        name='user-list'),
    path('users/<int:pk>/',
        views.UserDetail.as_view(),
        name='user-detail')
])

Pagination

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}

'Django' 카테고리의 다른 글

Writing Custom django-admin command  (0) 2019.08.30
ViewSets & Routers  (0) 2019.08.29
REST API Authentication & Permissions  (0) 2019.08.29
Rest Framework Views  (0) 2019.08.29
Serializer  (0) 2019.08.29
최근에 올라온 글
글 보관함