首页 > 代码库 > django-rest-framework学习之Relationships & Hyperlinked APIs--2017年4月17日至18日

django-rest-framework学习之Relationships & Hyperlinked APIs--2017年4月17日至18日

 
Relationships & Hyperlinked APIs
 
参考链接:
http://www.weiguda.com/blog/23/
http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/
 
目前我们API中的关系用primary keys展示,这部分我们会通过hyperlinking提高我们API的内聚性和扩展性
 
【1】给API的根节点传建一个端点
在views.py中添加:
from rest_framework.decorators import api_view
from rest_framework.response import Response
#reverse函数返回完全合格的URLs
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),
        myLesson:reverse(myLesson-list,request=request,format=format)
    })
 
【2】为highlighted创建一个端点
和其他API不同的是,我们不用JSON格式,而是用HTML展示,Rest framework提供了两种风格的HTML Render,一个是使用模板,另一个用pre_rendererd,这里我们使用第二个
因为我们要返回的不是一个类,而是一个属性,所以没有我们能够是用的具体的generic view,所以我们用generics.GenericAPIView并自己创建get方法
 
在views.py中添加:
from rest_framework import renderers
 
class MyLessonHighlight(generics.GenericAPIView):
    queryset = MyLesson.objects.all()
    serializer_class = MyLessonSerializer
    renderer_classes = (renderers.StaticHTMLRenderer,)
    def get(self,request,*args,**kwargs):
        myLesson = self.get_object()
        return Response(myLesson.highlighted)
 
在mylesson中urls.py添加:
url(r^$, views.api_root),
url(r^myLesson/(?P<pk>[0-9]+)/highlight/$, views.MyLessonHighlight.as_view()),
 
【3】给API添加超链接
有很多方式可以展示实体间的关系:primary keys, hyperlinking, unique identifying slug field, default string, 或者使两个类继承自一个母体
REST framework 提供了上述所有风格,在此case中我们使用hyperlinked,使用HyperlinkedModelSerializer
HyperlinkedModelSerializer 和 ModelSerializer 的区别:没有id,多了url,用HyperlinkedRelatedField代替PrimaryKeyRelatedField
 
因此我们重写serializers.py
from rest_framework import serializers
from myLesson.models import MyLesson
from django.contrib.auth.models import User
 
class MyLessonSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.ReadOnlyField(source=owner.username)
    url = serializers.HyperlinkedIdentityField(view_name="myLesson-detail")
    highlight = serializers.HyperlinkedIdentityField(view_name=myLesson-highlight,format=html)
    class Meta:
        model = MyLesson
        fields = (url,id,highlight,owner,title,code,linenos,language,style)
 
 
class UserSerializer(serializers.HyperlinkedModelSerializer):
#    myLesson = serializers.PrimaryKeyRelatedField(many=True,queryset=MyLesson.objects.all())
    myLesson = serializers.HyperlinkedRelatedField(many=True,view_name=myLesson-detail,read_only=True)
    class Meta:        model = User
        fields = (url,id,username,myLesson)
 
【4】确认URL patterns已经被命名
 
修改myLesson/urls.py:
from django.conf.urls import url,include
from myLesson import views
from rest_framework.urlpatterns import format_suffix_patterns
 
urlpatterns = [
    url(r^$,views.api_root),
    url(r^users/$,views.UserList.as_view(),name=user-list),
    url(r^users/(?P<pk>[0-9]+)/$,views.UserDetail.as_view(),name=user-detail),
    url(r^myLesson/$,views.MyLessonList.as_view(),name=myLesson-list),
    url(r^myLesson/(?P<pk>[0-9]+)/$,views.MyLessonDetail.as_view(),name=myLesson-detail),    url(r^myLesson/(?P<pk>[0-9]+)/highlight/$,views.MyLessonHighlight.as_view(),name=myLesson-highlight),]
 
urlpatterns = format_suffix_patterns(urlpatterns)
 
【5】添加分页
如果数据库中的数据达到一定程度, 那么用户使用api时可能会返回大量数据, 因此, 我们最好使用分页功能。
我们可以使用django-rest-framework自带的设置选项, 使list自动使用分页:
# myTest/settings.py
    REST_FRAMEWORK = {
        PAGINATE_BY: 10
    }

【6】修改bug,按照官网文档的代码写完运行调试,有bug,报错

Could not resolve URL for hyperlinked relationship using view name "mylesson-detail". You may have failed to include the related model in your API, or incorrectly configured the lookup_field attribute on this field.

修改问题参考链接:http://stackoverflow.com/questions/20550598/django-rest-framework-could-not-resolve-url-for-hyperlinked-relationship-using

解决办法:在MyLessonSerializer中添加url说明:

url = serializers.HyperlinkedIdentityField(view_name="myLesson-detail")

django-rest-framework学习之Relationships & Hyperlinked APIs--2017年4月17日至18日