django-rest-framework学习之路-6-关系和超链接API
django-rest-framework学习之路-6-关系和超链接API
1、创建根路由
我们的项目没有一个根路由,现在我们来创建一个根路由,使用之前介绍的@api_view装饰器
在snippets/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)
})
snippets/views.py变成了
from django.contrib.auth.models import User
from rest_framework import generics, permissions
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from snippets.models import Snippet
from snippets.permissions import IsOwnerOrReadOnly
from snippets.serializers import SnippetSerializer, 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 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):
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class UserList(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class UserDetail(generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
在snippets/urls.py注册路由
path(r'', views.api_root),
并且我们需要改动一下之前的snippets_list路由,给它添加一个路由别名,叫snippet-lis
给users也添加一个路由别名,叫user-list
同时也取出detail的路由别名user-detail和snippet-detail
所以snippets/urls.py变成了
from django.urls import re_path, path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
re_path(r'^snippets_list/$', views.SnippetList.as_view(), name='snippet-list'),
re_path(r'^snippets_detail/(?P[0-9]+)/$', views.SnippetDetail.as_view(),name='snippet-detail'),
re_path(r'^users/$', views.UserList.as_view(), name='user-list'),
re_path(r'^users/(?P[0-9]+)/$', views.UserDetail.as_view(),name='user-detail'),
path('', views.api_root),
]
urlpatterns = format_suffix_patterns(urlpatterns)
我们需要定义一个接口,只用于返回高亮的代码
我们只需要把代码中需要高亮的代码返回,然后进行渲染即可,因为我们返回的是Snippet实例的一个属性,也就是highlighted属性,我们不用自动生成其他的方式,比如post、put、delete,我们只需要生成一个get接口,获取到实例的highlighted字段即可,所以我们继承基础类GenericAPIView类
我们还需要使用html渲染,使用使用StaticHTMLRenderer模板进行渲染
然后我们重写get方法
在snippets/views.py中添加
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)
在snippets/urls.py注册路由
re_path(r'^snippets_list/(?P[0-9]+)/highlight/$', views.SnippetHighlight.as_view(), name='highlight'),
最终snippets/urls.py
from django.urls import re_path, path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
re_path(r'^snippets_list/$', views.SnippetList.as_view(), name='snippet-list'),
re_path(r'^snippets_detail/(?P[0-9]+)/$', views.SnippetDetail.as_view(),name='snippet-detail'),
re_path(r'^users/$', views.UserList.as_view(), name='user-list'),
re_path(r'^users/(?P[0-9]+)/$', views.UserDetail.as_view(),name='user-detail'),
re_path(r'^snippets_list/(?P[0-9]+)/highlight/$', views.SnippetHighlight.as_view(), name='snippet-highlight'),
path('', views.api_root),
]
urlpatterns = format_suffix_patterns(urlpatterns)
使用HyperlinkedModelSerializer来添加超链接
我们想要使用超链接的形式来显示外键关系
或者我们想要自己添加超链接视图,例如我们的highlighted超链接
我们把ModelSerializer变成HyperlinkedModelSerializer
通过HyperlinkedIdentityField关联超链接字段
HyperlinkedModelSerializer与ModelSerializer有以下区别:
- 默认情况下不包括id字段。
- 它包含一个url字段,使用HyperlinkedIdentityField。
- 关联关系使用HyperlinkedRelatedField,而不是PrimaryKeyRelatedField。
snippets/serializers.py变成了:
from django.contrib.auth.models import User
from rest_framework import serializers
from snippets.models import Snippet
# class SnippetSerializer(serializers.ModelSerializer):
# owner = serializers.ReadOnlyField(source='owner.username')
#
# class Meta:
# model = Snippet
# fields = ('id', 'owner', 'title', 'code', 'linenos', 'language', 'style')
#
#
# class UserSerializer(serializers.ModelSerializer):
# snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())
#
# class Meta:
# model = User
# fields = ('id', 'username', 'snippets')
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')
highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')表示这是一个超链接,超链接到snippet-highlight,格式是html
确保我们的URL都存在
在上面,我们定义了几个链接,我们要把它都申明出来,他们是:
user-list snippet-list snippet-highlight snippet-detail
来自于这些地方
所以我们的snippets/urls.py文件应该如下所示:
from django.urls import re_path, path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
re_path(r'^snippets_list/$', views.SnippetList.as_view(), name='snippet-list'),
re_path(r'^snippets_detail/(?P[0-9]+)/$', views.SnippetDetail.as_view(), name='snippet-detail'),
re_path(r'^users/$', views.UserList.as_view(), name='user-list'),
re_path(r'^users/(?P[0-9]+)/$', views.UserDetail.as_view(), name='user-detail'),
re_path(r'^snippets_list/(?P[0-9]+)/highlight/$', views.SnippetHighlight.as_view(), name='snippet-highlight'),
path('', views.api_root),
]
urlpatterns = format_suffix_patterns(urlpatterns)
添加分页
我们可以进行分页,不然显示在一页就太长了
修改tutorial/settings.py添加以下设置:
REST_FRAMEWORK = {
'PAGE_SIZE': 10
}
如果需要的话,我们也可以自定义分页风格,但在这个例子中,我们将一直使用默认设置。
浏览器查看
snippets 根路径 http://127.0.0.1:8000/snippets/
详情 http://127.0.0.1:8000/snippets/snippets_detail/3/
高亮 http://127.0.0.1:8000/snippets/snippets_list/3/highlight/
学习链接 : https://www.w3cschool.cn/lxraw/lxraw-eph335of.html