本节大纲javascript
一、Routershtml
二、Parsersjava
三、Renderersdjango
Usagejson
from rest_framework import routers router = routers.SimpleRouter() router.register(r'users', UserViewSet) router.register(r'accounts', AccountViewSet) urlpatterns = router.urls
register的两个必填参数prefix, viewset, 可选参数base_name,用于建立URL名称的基础。若是未设置,将根据视图集的queryset属性自动生成basename注意,若是视图集不包含queryset属性,那么在注册viewset时必须设置base_name。api
以前上一章关于视图集的截图里面其实就已经能够发现这一点。浏览器
样例:网络
若是都没有定义会报错app
'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
Using include with routers框架
能够添加路由以下
router = routers.SimpleRouter() router.register(r'users', UserViewSet) router.register(r'accounts', AccountViewSet) urlpatterns = [ url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), ] urlpatterns += router.urls
另外,可使用Django的include方法
urlpatterns = [ url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), url(r'^', include(router.urls)), ]
也可使用include带上app的命名空间:
urlpatterns = [ url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), url(r'^api/', include((router.urls, 'app_name'))), ]
还能够带上app和实例的命名空间
urlpatterns = [ url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), url(r'^api/', include((router.urls, 'app_name'), namespace='instance_name')), ]
Routing for extra actions
经过@action装饰器来标记额外的操做,这些额外的操做会被包含在生成的url里面,好比上一章给的change_age等等
class StudentViewSet(ModelViewSet): queryset = PersonResource.objects.filter(job=1) serializer_class = PersonModelSerializer @action(methods=['get', 'put'], detail=True) def change_age(self, request, pk=None): student = self.get_object() student.age += 1 student.save() return Response({ 'status': '%s age changed.' % student.name, 'url': self.reverse_action('change-age', args=[pk]), 'url1': self.reverse_action(self.change_age.url_name, args=[pk]) }) @action(detail=False) def ordering(self, request): student = PersonResource.objects.filter(job=1).order_by('modify_time') page = self.paginate_queryset(student) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(student, many=True) return Response(serializer.data)
若是想要修改客制化的action的url
from myapp.permissions import IsAdminOrIsSelf from rest_framework.decorators import action class UserViewSet(ModelViewSet): ... @action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf], url_path='change-password', url_name='change_password') def set_password(self, request, pk=None): ...
API Guide
SimpleRouter
默认ULRs经过SimpleRouter建立,添加trailing_slash参数。这个行为能够被修改经过设置trailing_slash参数为False当初始化router
router = SimpleRouter(trailing_slash=False)
尾随斜杠在Django中是常规的,但在某些其余框架(如Rails)中默认不使用。您选择使用哪一种样式在很大程度上取决于首选项,尽管一些javascript框架可能但愿使用特定的路由样式。
路由器将匹配包含除斜线和周期字符以外的任何字符的查找值。对于更严格(或宽松)的查找模式,在VIEW集中设置lookup_value_regex属性。例如,能够将查找限制为有效UUIDs:
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet): lookup_field = 'my_model_id' lookup_value_regex = '[0-9a-f]{32}'
DefaultRouter
一样
router = DefaultRouter(trailing_slash=False)
源文档这边是讲了关于客制化路由,动态路由参数的内容,不过,从个人生产上没感受到有这个需求,暂时就不看了,先补个连接,有空补充这一块的知识点。
http://www.django-rest-framework.org/api-guide/routers/
REST framework包含了不少内置的Parser类。容许接受不少种媒体类别请求。它也支持定义你本身的客制化解析。
视图的合法解析器老是定义为一个列表类,当request.data能够访问的时候,rest framework将检查即将到来的请求头的content-type,决定用哪一个解析器来解析request的内容。
Setting the parsers
能够经过使用DEFAULT_PARSER_CLASSES
来进行全局设置。好比,下面的设定仅容许JSON内容,代替默认的JSON或者表单数据
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', ) }
你也能够为一个单独的视图或者视图集设置,使用APIView CBV格式。
from rest_framework.parsers import JSONParser from rest_framework.response import Response from rest_framework.views import APIView class ExampleView(APIView): """ A view that can accept POST requests with JSON content. """ parser_classes = (JSONParser,) def post(self, request, format=None): return Response({'received data': request.data})
或者若是用FBV格式的话
from rest_framework.decorators import api_view from rest_framework.decorators import parser_classes from rest_framework.parsers import JSONParser @api_view(['POST']) @parser_classes((JSONParser,)) def example_view(request, format=None): """ A view that can accept POST requests with JSON content. """ return Response({'received data': request.data})
API Reference
JSONParser # 解析成json请求内容;.media_tyoe:application/json MultiPartParser # 解析HTML表单内容,request.data返回QueryDict数据,你须要使用FormParser和MultiPartParser,来彻底支持html表单数据;.media_type:application/x-www-form-urlencoded MultiPartParser # 同上;.media_type:multipart/form-data FileUploadParser # 解析源生的上传文件内容,request.data属性将会是一个字典,包含一个单独的键'file'对应上传文件内容。若是使用文件名url关键字参数调用FIleUploadParser使用的视图,则该参数讲用做filename。若是没有filename url关键字参数,客户端必须设置文件名在请求头的Content-Disposition里面。好比:Content-Disposition: attachment; filename=upload.jpg;.media_type:*/*
注意:
a、FileUploadParser是用来给能够上传文件做为源生数据请求的本地客户端使用。对于基于网络的上传,或者具备多部分上传支持的本地客户端,你须要使用MultiPartParser代替.
b、因为这个parser的media_type匹配任何的内容类型,FileUploadParser通常是惟一的parser在API视图上
c、FileUploadParser遵循Django标准的
FILE_UPLOAD_HANDLERS
设定和request.upload_handlers
属性.
# views.py class FileUploadView(views.APIView): parser_classes = (FileUploadParser,) def put(self, request, filename, format=None): file_obj = request.data['file'] # ... # do some stuff with uploaded file # ... return Response(status=204) # urls.py urlpatterns = [ # ... url(r'^upload/(?P<filename>[^/]+)$', FileUploadView.as_view()) ]
Third party packages
YAML
$ pip install djangorestframework-yaml
# Django setting REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework_yaml.parsers.YAMLParser', ), 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework_yaml.renderers.YAMLRenderer', ), }
XML
$ pip install djangorestframework-xml
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework_xml.parsers.XMLParser', ), 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework_xml.renderers.XMLRenderer', ), }
setting the renderers
如下设置将使用JSON做为主媒体类型,还包括自描述API。全局的设定使用DEFAULT_RENDERER_CLASSES
参数
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ) }
能够单独对一个视图或者视图集设置,使用APIView的CBV格式
from django.contrib.auth.models import User from rest_framework.renderers import JSONRenderer from rest_framework.response import Response from rest_framework.views import APIView class UserCountView(APIView): """ A view that returns the count of active users in JSON. """ renderer_classes = (JSONRenderer, ) def get(self, request, format=None): user_count = User.objects.filter(active=True).count() content = {'user_count': user_count} return Response(content)
或者在FBV格式下,使用@api_view装饰器
@api_view(['GET']) @renderer_classes((JSONRenderer,)) def user_count_view(request, format=None): """ A view that returns the count of active users in JSON. """ user_count = User.objects.filter(active=True).count() content = {'user_count': user_count} return Response(content)
API Reference
JSONRenderer
转成json,使用utf-8编码。默认是使用unicode字符,渲染响应使用紧凑型的格式,没有没必要要的空格
{"unicode black star":"★","value":999}
客户端可能会额外的包含一个indent媒体类型参数,从而让返回的json数据被缩进。好比Accept: application/json; indent=4
{ "unicode black star": "★", "value": 999 }
默承认以选择UNICODE_JSON
和COMPACT_JSON
.media_type: application/json
.format: '.json'
.charset: None
TemplateHTMLRenderer
模板渲染传入Response跟其余的转换不同,它不须要被序列化,你只须要包含template_name参数当建立Response实例对象的时候
TemplateHTMLRenderer会建立一个RequestContext,使用response.data做为内容字典根据,并肯定用于呈现上下文的模板名称。
模板名称能够经过如下几种方式定义:
一、明确的定义template_name传入response
二、明肯定义.template_name属性在类上
三、调用view.get_template_names()
方法返回结果
class UserDetail(generics.RetrieveAPIView): """ A view that returns a templated HTML representation of a given user. """ queryset = User.objects.all() renderer_classes = (TemplateHTMLRenderer,) def get(self, request, *args, **kwargs): self.object = self.get_object() return Response({'user': self.object}, template_name='user_detail.html')
你可使用TemplateHTMLRenderer
返回常规的使用rest框架的html,或者是从同一个终端的HTML和API响应一块儿
若是您正在构建使用TemplateHTMLRenderer和其余渲染类的网站,那么应该考虑将TemplateHTMLRenderer做为renderer_classes列表中的第一个类列出,这样即便对于发送格式不佳的ACCEPT:header的浏览器,也会优先考虑它。
StaticHTMLRenderer
传入到response的数据是字符串类型
@api_view(('GET',)) @renderer_classes((StaticHTMLRenderer,)) def simple_html_view(request): data = '<html><body><h1>Hello, world</h1></body></html>' return Response(data)
Third party packages
YAML
$ pip install djangorestframework-yaml
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework_yaml.parsers.YAMLParser', ), 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework_yaml.renderers.YAMLRenderer', ), }
XML
$ pip install djangorestframework-xml
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework_xml.parsers.XMLParser', ), 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework_xml.renderers.XMLRenderer', ), }
JSONP
$ pip install djangorestframework-jsonp
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework_jsonp.renderers.JSONPRenderer', ), }
附上连接,至少目前感受,这边真的不怎么用获得
http://www.django-rest-framework.org/api-guide/renderers/