Computer Science/BackEnd
장고 DRF #5 | Django REST framework Relationships & Hyperlinked APIs
토마토.
2022. 9. 10. 09:13
5 - Relationships and hyperlinked APIs - Django REST framework (django-rest-framework.org)
5 - Relationships and hyperlinked APIs - Django REST framework
At the moment relationships within our API are represented by using primary keys. In this part of the tutorial we'll improve the cohesion and discoverability of our API, by instead using hyperlinking for relationships. Right now we have endpoints for 'snip
www.django-rest-framework.org
Django REST Framework
Relationships & Hyperlinked APIs
Creating an endpoint for the root of our API
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from rest_framework import generics, permissions
from django.contrib.auth.models import User
from snippets.permissions import IsOwnerOrReadOnly
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
serializer_class = SnippetSerializer
class UserList(generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
@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)
})
- Response : 정규화된 URL을 반환하는 rest framework 함수
Creating an endpoint for the highlighted snippets
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from rest_framework import generics, permissions, renderers
from django.contrib.auth.models import User
from snippets.permissions import IsOwnerOrReadOnly
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
serializer_class = SnippetSerializer
class UserList(generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
@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)
})
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)
Hyperlinking our API
- 엔티티 간의 관계를 표현하는 방식
- primary key 사용하기
- 하이퍼링크 사용하기
- 등등
from rest_framework import serializers
from django.contrib.auth.models import User
from snippets.models import Snippet, LANGUAGE_CHOICES,STYLE_CHOICES
class SnippetSerializer(serializers.Serializer):
owner = serializers.ReadOnlyField(source='owner.username')
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(required=False, allow_blank=True, max_length=100)
code = serializers.CharField(style={'base_template':'textarea.html'})
linenos = serializers.BooleanField(required=False)
language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
def create(self, validated_data):
return Snippet.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.code = validated_data.get('code', instance.code)
instance.linenos = validated_data.get('linenos', instance.linenos)
instance.language = validated_data.get('language', instance.language)
instance.style = validated_data.get('style', instance.style)
instance.save()
return instance
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, include
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')
])
Adding pagination
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE':10
}