Django REST framework 是用于构建 Web API(网络应用程序接口) 的强大而灵活的工具包,利用它我们可以自动生成符合 RESTful 规范的 API 、生成 Browserable 的交互页面以及非常细粒度的权限管理等。
选择使用 REST 框架的一些原因:
- Web浏览API对于开发人员来说是一个巨大的可用性
- 认证策略包括OAuth1a和OAuth2的包
- 支持ORM和非ORM数据源的序列化
- 如果你不需要更强大的功能,就可以使用常规的基于功能的视图
- 广泛的文档和良好的社区支持
Django Rest framework 大概有如下流程:
- 创建数据模型
- 依靠 Serialiers 将数据库取出的数据 Parse 为 API 的数据(可用于返回给客户端,也可用于浏览器显示)
- 权限设置(对象级别、系统级别等权限管理)
- ViewSet 是一个 views 的集合,根据客户端的请求(GET、POST等),返回 Serialiers 处理的数据
- ViewSet 可在 Routers 进行注册,注册后会显示在 Api Root 页上
- 在 URLs 里注册 ViewSet 生成的 view
基础配置
为该项目创建一个单独的虚拟环境用于隔离其它环境。
mkvirtualenv mydrf pip install django pip install djangorestframework pip install pygments # 用于代码高亮显示 pip install pymysql
创建 Django 项目及 APP
- 在虚拟环境下创建 Django 项目
(mydrf) allenlideMacBook-Pro:~ allen$ django-admin.py startproject mydrf
- 创建 APP
python manage.py startapp snippets # 用于处理数据 python manage.py startapp api # 用于处理 API
- 注册 APP
# settings.py INSTALLED_APPS = ( ... 'rest_framework', 'snippets', 'api', )
- 配置数据库连接
# settings.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mydrf', 'USER': 'root', 'PASSWORD': 'password', 'HOST': '127.0.0.1', 'PORT': 3306, 'OPTIONS': {'charset': 'utf8',} } } # __init__.py import pymysql pymysql.install_as_MySQLdb()
- 设置 REST_FRAMEWORK
# settings.py REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.AllowAny', ), 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', 'PAGE_SIZE': 10 # 分页 }
创建数据模型
- Snippet 数据模型
# snippets/models.py from django.db import models from pygments.lexers import get_all_lexers LEXERS = [item for item in get_all_lexers() if item[1]] LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS]) class Snippet(models.Model): title = models.CharField(max_length=100, blank=True, default='') code = models.TextField() language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100) created = models.DateTimeField(auto_now_add=True) class Meta: ordering = ('created',) def __str__(self): return self.title
- 注册 Snippet 模型类
# snippets/admin.py from django.contrib import admin from .models import Snippet @admin.register(Snippet) class SnippetAdmin(admin.ModelAdmin): list_display = ('title', 'code', 'language', 'created')
- 生成数据库
python manage.py makemigrations python manage.py migrate
- 创建超级用户
python manage.py createsuperuser
序列化
Serializers 用于将复杂的数据结构,例如 ORM 中的 QuerySet 或者 Model 实例对象转换成 Python 内置的数据类型,从而进一步方便数据和 json,xml 等格式的数据进行交互。
通常情况下,前端调用后台 API,API 需要返回数据给前端,而返回的数据类型一般以 JSON 格式为主。
Serializers 则可以实现如下功能:
- 序列化 -- 将 Python Model 实例对象转换为 JSON 格式,返回给前端
- 反序列化 -- 将前端传给后台的 JSON 数据转换为 Python Model 实例对象
使用 Serializer 类
- 创建序列化类
# api/serializers.py from rest_framework import serializers from snippets.models import Snippet, LANGUAGE_CHOICES class SnippetSerializer(serializers.Serializer): 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'}) language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python') def create(self, validated_data): ''' 根据提供的验证过的数据创建并返回一个新的 `Snippet` 实例。 ''' return Snippet.objects.create(**validated_data) def update(self, instance, validated_data): ''' 根据提供的验证过的数据更新和返回一个已经存在的 `Snippet` 实例。 ''' instance.title = validated_data.get('title', instance.title) # instance.title 为默认值 instance.code = validated_data.get('code', instance.code) instance.language = validated_data.get('language', instance.language) instance.save() return instance
- 序列化器类的第一部分,告诉REST框架,哪些字段需要进行序列化/反序列化
- create() 和 update() 方法定义了在调用 serializer.save() 时如何创建和修改完整的实例
- 序列化器类与 Django Form 类非常相似,并在各种字段中包含类似的验证标志,例如 required,max_length 和 default
- {'base_template': 'textarea.html'} 标识,相当于在 Django 的 Form 类中使用 widget=widgets.Textarea,用于 HTML 渲染。
- 使用序列化程序
# python manage.py shell >>> from snippets.models import Snippet >>> from api.serializers import SnippetSerializer >>> from rest_framework.renderers import JSONRenderer # 输出格式为json格式 >>> from rest_framework.parsers import JSONParser # 输入格式为json格式
实例化类
>>> snippet = Snippet(code='foo = "bar"\n') >>> snippet.save() >>> snippet = Snippet(code='print "hello, world"\n') >>> snippet.save()
获取 python 数据类型的数据
>>> serializer = SnippetSerializer(snippet) >>> serializer.data {'id': 2, 'title': '', 'code': 'print "hello, world"\n', 'language': 'python'}
此时,我们将模型实例转换为 Python 原生数据类型,要完成序列化过程,我们将数据转换成 json
>>> content = JSONRenderer().render(serializer.data) >>> content b'{"id":2,"title":"","code":"print \\"hello, world\\"\\n","language":"python"}'
反序列化是类似的,首先我们将一个流(stream)解析为 Python 原生数据类型
>>> from django.utils.six import BytesIO >>> stream = BytesIO(content) # 读取 >>> data = JSONParser().parse(stream) # 解析 >>> data {'id': 2, 'title': '', 'code': 'print "hello, world"\n', 'language': 'python'}
然后我们要将 Python 原生数据类型恢复成正常的对象实例
>>> serializer = SnippetSerializer(data=data) # 反向还原(反序列化) >>> serializer.is_valid() # 验证还原数据 True >>> serializer.validated_data # 查看还原数据 OrderedDict([('title', ''),('code', 'print "hello, world"'),('language', 'python')]) >>> serializer.save() # 保存 <Snippet: >
检查数据
对 JSON 格式字典进行校验并写入数据模型中
>>> snippet = {'code':'Django REST Framework.'} >>> s = SnippetSerializer(data=snippet) >>> s.is_valid() True >>> s.save() <Snippet: >
检查数据>
使用 many=True 标志,序列化查询结果集而不是模型实例
>>> serializer = SnippetSerializer(Snippet.objects.all(), many=True) >>> serializer.data [OrderedDict([('id', 1), ('title', ''), ('code', 'foo = "bar"\n'), ('language', 'python')]), OrderedDict([('id', 2), ('title', ''), ('code', 'print "hello, world"\n'), ('language', 'python')]), OrderedDict([('id', 3), ('title', ''), ('code', 'print "hello, world"'), ('language', 'python')]), OrderedDict([('id', 4), ('title', ''), ('code', 'Django REST Framework.'), ('language', 'python')])]
- 在视图中使用 Serializer 类
创建一个 HttpResponse 的子类,这个子类会将任何 data 渲染并返回为 json
# api/views.py from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParser from snippets.models import Snippet from api.serializers import SnippetSerializer class JSONResponse(HttpResponse): ''' An HttpResponse that renders its content into JSON. ''' def __init__(self, data, **kwargs): content = JSONRenderer().render(data) kwargs['content_type'] = 'application/json' super(JSONResponse, self).__init__(content, **kwargs)
因为我们需要 POST 数据到这个视图的客户端,但并没有 CSRF 令牌(token),所以我们需要将该视图标记为 csrf_exempt
# api/views.py @csrf_exempt def snippet_list(request): ''' 列出所有的 `Snippet`,或创建一个新的 `Snippet` ''' if request.method == 'GET': snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return JSONResponse(serializer.data) elif request.method == 'POST': data = JSONParser().parse(request) serializer = SnippetSerializer(data=data) if serializer.is_valid(): serializer.save() return JSONResponse(serializer.data, status=201) return JSONResponse(serializer.errors, status=400) @csrf_exempt def snippet_detail(request, pk): ''' 获取、更新或删除一个 `Snippet` ''' try: snippet = Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: return HttpResponse(status=404) if request.method == 'GET': serializer = SnippetSerializer(snippet) return JSONResponse(serializer.data) elif request.method == 'PUT': data = JSONParser().parse(request) serializer = SnippetSerializer(snippet, data=data) if serializer.is_valid(): serializer.save() return JSONResponse(serializer.data) return JSONResponse(serializer.errors, status=400) elif request.method == 'DELETE': snippet.delete() return HttpResponse(status=204)
- 配置 URLs 访问数据
# urls.py from django.conf.urls import url, include urlpatterns = [ ..., url(r'^api/', include('api.urls')), ] # api/urls.py 路由分发 from django.conf.urls import url from . import views app_name='api' urlpatterns = [ url(r'^snippets/$', views.snippet_list), url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail), ]
- 测试 API
启动服务
python manage.py runserver
访问所有的 Snippet 列表
通过引用其 id 来访问特定的 Snippet
使用 ModelSerializer 类(**)
就像 Django 提供了 Form 类和 ModelForm 类一样,REST framework 也包括 Serializer 类和 ModelSerializer 类
仅修改 serializers.py 文件, views 和 urls 文件不用更改。
# api/serializers.py from rest_framework import serializers from snippets.models import Snippet class SnippetSerializer(serializers.ModelSerializer): class Meta: model = Snippet fields = ('id', 'title', 'code', 'language')
ModelSerializer 类并不会做任何特别神奇的事情,它们只是创建序列化器类的快捷方式:
- 一组自动确定的字段或全部字段
- 默认简单实现的 create() 和 update() 方法
使用 ModelSerializer 类
# python manage.py shell >>> from snippets.models import Snippet >>> from api.serializers import SnippetSerializer >>> snippet = {'code':'Django REST Framework By ModelSerializer.'} >>> s = SnippetSerializer(data=snippet) >>> s.is_valid() True >>> s.save() <Snippet: >
请求和响应
请求对象
REST framework 引入了一个 Request 对象, 它继承自普通的 HttpRequest ,但能够更加灵活的解析收到的请求。Request 对象的核心功能,就是其中的 request.data 属性。这个属性跟 request.POST 相似,但对我们的 Web API来说,更加的有用。
request.POST # 只能处理表单数据,只能处理 'POST' 方法. request.data # 可处理任意数据.可以处理 'POST', 'PUT' 和 'PATCH'方法
响应对象
REST 框架还引入了一个 Response 对象,是一种 TemplateResponse ,它携带着纯粹的内容(未经过渲染),通过内容协商(Content Negotiation)来决定将以何种形式,返回给客户端。
return Response(data) # 根据客户端的要求,渲染成不同的内容类型
状态码
在视图中,使用纯数字的状态码,并不利于代码阅读,如果你写错了状态码,也不会很容易的察觉。REST framework 为每个状态码提供了更加明确的标识,比如 HTTP_400_BAD_REQUEST,这些标识符在 status 模块中。
from rest_framework import status
包装API视图
REST 框架提供了两个可用于编写API视图的包装器:
- 用于处理基于函数视图的装饰器 @api_view
- 用于处理基于类视图的 APIView 类
这些包装器提供了一些功能,例如确保你在视图能够接收到 Request 实例,并将上下文添加到 Response 对象,以便可以执行内容协商;
这些包装器还内置了一些行为,例如在遇到错误请求时,自动响应 405 Method Not Allowed; 在处理 request.data 时,因为输入的格式不恰当,而发生的任何 ParseError 异常。
将所有元素组合在一起
- 使用包装器重新编写视图
# api/views.py from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response from snippets.models import Snippet from api.serializers import SnippetSerializer @api_view(['GET', 'POST']) def snippet_list(request): ''' 列出所有的 `Snippet`,或者创建一个新的 `Snippet` ''' if request.method == 'GET': snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = SnippetSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(['GET', 'PUT', 'DELETE']) def snippet_detail(request, pk): ''' 获取,更新或删除一个 `Snippet` 实例 ''' try: snippet = Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'GET': serializer = SnippetSerializer(snippet) return Response(serializer.data) elif request.method == 'PUT': serializer = SnippetSerializer(snippet, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE': snippet.delete() return Response(status=status.HTTP_204_NO_CONTENT)
- 为 URLs 添加可选的格式后缀 为了充分利用我们的响应不再与单一内容类型连接,我们可以为 API 路径添加对格式后缀的支持。使用格式后缀给我们明确指定了给定格式的 URLs,这意味着我们的 API 将能够处理诸如 http://example.com/api/items/4.json 之类的 URL
在视图中添加一个 format 关键字参数
# api/views.py def snippet_list(request, format=None): def snippet_detail(request, pk, format=None):
配置 URLs
# api/urls.py from django.conf.urls import url from rest_framework.urlpatterns import format_suffix_patterns from . import views app_name='api' urlpatterns = [ url(r'^snippets/$', views.snippet_list), url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail), ] urlpatterns = format_suffix_patterns(urlpatterns)
访问所有的 Snippet 列表
通过引用其 id 来访问特定的 Snippet
使用 httpie 测试服务器
pip install httpie
通过附加格式后缀,控制回复的响应格式
http http://127.0.0.1:8000/api/snippets.json HTTP/1.1 200 OK Content-Type: application/json [ { "code": "foo = \"bar\"\n", "id": 1, "language": "python", "title": "" }, { "code": "print \"hello, world\"\n", "id": 2, "language": "python", "title": "" } ]
POST 表单数据,新增 Snippet
http --form POST http://127.0.0.1:8000/api/snippets/ code="print 123" HTTP/1.1 201 Created { "code": "print 123", "id": 13, "language": "python", "title": "" }
POST JSON 数据,新增 Snippet
http --json POST http://127.0.0.1:8000/api/snippets/ code="print 456" HTTP/1.1 201 Created { "code": "print 456", "id": 14, "language": "python", "title": "" }
PUT 表单数据,修改 Snippet
http --form PUT http://127.0.0.1:8000/api/snippets/13/ code="print 789" HTTP/1.1 200 OK { "code": "print 789", "id": 13, "language": "python", "title": "" }
DELETE JSON 数据, 删除 Snippet
http --json DELETE http://127.0.0.1:8000/api/snippets/14/ HTTP/1.1 204 No Content
视图
基于类的视图
- 编写视图
# api/views.py from django.http import Http404 from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from snippets.models import Snippet from api.serializers import SnippetSerializer class SnippetList(APIView): ''' 列出所有的 `Snippet` 或者创建一个新的 `Snippet` ''' def get(self, request, format=None): snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return Response(serializer.data) def post(self, request, format=None): serializer = SnippetSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class SnippetDetail(APIView): ''' 检索,更新或删除一个 `Snippet` 示例 ''' def get_object(self, pk): # 重写 get_obj 方法,根据 pk 查找文章分类 try: return Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: raise Http404 def get(self, request, pk, format=None): snippet = self.get_object(pk) # 获取对象 serializer = SnippetSerializer(snippet) return Response(serializer.data) def put(self, request, pk, format=None): snippet = self.get_object(pk) serializer = SnippetSerializer(snippet, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, pk, format=None): snippet = self.get_object(pk) snippet.delete() return Response(status=status.HTTP_204_NO_CONTENT)
- 配置 URLs
# api/urls.py from django.conf.urls import url from . import views app_name='api' urlpatterns = [ url(r'^snippets/$', views.SnippetList.as_view()), url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()), ]
通用的基于类的视图
- 编写视图
# api/views.py from rest_framework import generics from snippets.models import Snippet from api.serializers import SnippetSerializer class SnippetList(generics.ListCreateAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer
- 配置 URLs
# api/urls.py from django.conf.urls import url from . import views app_name='api' urlpatterns = [ url(r'^snippets/$', views.SnippetList.as_view()), url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()), ]
认证和权限(**)
目前,我们的API对谁可以编辑或删除代码段没有任何限制。我们希望有更高级的行为,以确保:
- 代码片段始终与创建者相关联
- 只有通过身份验证的用户可以创建片段
- 只有代码片段的创建者可以更新或删除它
- 未经身份验证的请求应具有完全只读访问权限
关联 User 与 Snippet 模型
- Snippet 模型增加用户字段
# snippets/models.py from django.contrib.auth.models import User class Snippet(models.Model): owner = models.ForeignKey(User, related_name='snippets', on_delete=models.CASCADE) ...,
- 生成数据库 因为存在外键关联关系,所以在生成数据库的时候,需要指定默认值
python manage.py makemigrations snippets python manage.py migrate snippets
- 序列化类中新增该字段
# api/serializers.py class SnippetSerializer(serializers.ModelSerializer): class Meta: model = Snippet fields = ('id', 'title', 'code', 'language', 'owner')
- 访问 URLs
- 修改显示内容(更新序列化类) 由上图可知,owner 字段显示的是用户 id,如果需要显示用户 name,还需要进行如下修改
# api/serializers.py class SnippetSerializer(serializers.ModelSerializer): owner = serializers.ReadOnlyField(source='owner.username') # 关联用户 class Meta: model = Snippet fields = ('id', 'title', 'code', 'language', 'owner')
- source 参数控制哪个属性用于填充字段,并且可以指向序列化实例上的任何属性
- 无类型的 ReadOnlyField 类始终是只读的,只能用于序列化表示,不能用于在反序列化时更新模型实例
- 访问 URLs
- 新增一个用户
python manage.py createsuperuser
- 回收该用户的 Superuser 权限(用于区分 admin 用户)
自定义权限(录入用户权限)
设置只有数据录入用户才有权限进行编辑或修改,其它用户只有只读权限
- 使用 has_object_permission(对象权限), 需传递数据对象
# api/permissions.py from rest_framework import permissions class IsOwnerOrReadOnly(permissions.BasePermission): ''' 自定义权限-只允许对象的所有者进行编辑/删除 此处 obj 表示 Snippet 对象 ''' def has_object_permission(self, request, view, obj): # 读取的权限允许任何请求 # 所以我们总是允许 GET 、HEAD 、OPTIONS 请求 if request.method in permissions.SAFE_METHODS: return True # 只有对象的所有者才允许写权限 # 返回 True/False True 代表有权限,False 代表无权限 return obj.owner == request.user
- 在 API 界面新增用户登录/注销接口
# urls.py urlpatterns = [ ..., url(r'^api-auth/', include(('rest_framework.urls', 'api-auth'), namespace='rest_framework')) ]
- 新增 Snippet 模型对象(录入人员为 admin2)
# python manage.py shell >>> from snippets.models import Snippet >>> from django.contrib.auth.models import User >>> u = User.objects.get(pk=2) >>> s = Snippet(code='@login_required', owner=u) >>> s.save()
- 修改视图,加入自定义权限认证
# api/views.py from rest_framework import generics from .serializers import SnippetSerializer from .permissions import IsOwnerOrReadOnly from snippets.models import Snippet class SnippetList(generics.ListCreateAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (IsOwnerOrReadOnly, ) # 注意这里是元祖 def perform_create(self, serializer): ''' 重写 perform_create 方法,在保存模型实例时,会自动将录入用户写入模型实例 ''' serializer.save(owner=self.request.user) class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (IsOwnerOrReadOnly, )
重写 perform_create 方法的作用: 将当前登录用户写入数据模型实例中
-
验证 admin 用户是否有权限编辑/删除(非录入人员) 非录入人员无 "PUT" 窗口
-
验证 admin2 用户是有否权限编辑/删除(录入人员)
自定义权限(管理员权限)
设置只有管理员(Superuser)用户才有权限进行编辑或修改,其它用户只有只读权限(录入人员也无法修改)
- 使用 has_permission(系统级权限)
# permissions.py from rest_framework import permissions class IsAdminUserOrReadOnly(permissions.BasePermission): def has_permission(self, request, view): ''' 系统级权限,不接受 obj 对象 ''' if request.method in permissions.SAFE_METHODS: return True return request.user and request.user.is_superuser
- 修改视图,加入自定义权限认证
# api/views.py from rest_framework import generics from .serializers import SnippetSerializer from .permissions import IsAdminUserOrReadOnly from snippets.models import Snippet class SnippetList(generics.ListCreateAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (IsAdminUserOrReadOnly, ) def perform_create(self, serializer): ''' 重写 perform_create 方法,在保存模型实例时,会自动将录入用户写入模型实例 ''' serializer.save(owner=self.request.user) class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (IsAdminUserOrReadOnly, )
-
验证 admin2 用户是有否权限编辑/删除(录入人员且非管理员身份)
-
验证 admin 用户是有否权限编辑/删除(非录入人员但是管理员身份)
视图集和路由(**)
使用 ViewSet
ViewSet 类仅在最后一刻被绑定到一组方法处理程序,当它被实例化成一组视图的时候,通常通过使用一个 Router 类来处理自己定义 URL conf 的复杂性
# api/views.py from rest_framework import viewsets, permissions from .serializers import SnippetSerializer from .permissions import IsAdminUserOrReadOnly from snippets.models import Snippet class SnippetViewSet(viewsets.ModelViewSet): queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (IsAdminUserOrReadOnly, ) # 系统级权限 def perform_create(self, serializer): ''' 重写 perform_create 方法,在保存模型实例时,会自动将录入用户写入模型实例 ''' serializer.save(owner=self.request.user)
路由 URLs
使用路由器,将 ViewSets 绑定到 url
# urls.py from django.contrib import admin from django.conf.urls import url, include urlpatterns = [ ..., url(r'api/', include('api.urls')), url(r'^api-auth/', include(('rest_framework.urls', 'api-auth'), namespace='rest_framework')) ] # api/urls.py from django.conf.urls import url, include from rest_framework.routers import DefaultRouter from . import views router = DefaultRouter() router.register(r'snippets', views.SnippetViewSet) app_name='api' urlpatterns = [ url(r'', include(router.urls)), # 添加 router 的 url ]
模式和文档
模式是一种机器可读的文档,描述可用的 API 端点、它们的 URLs 以及它们支持的操作
模式可以是自动生成文档的有用工具,也可以用于驱动可以与 API 交互的动态客户端库
- 安装 coreapi 包
pip install coreapi
- 在 URLs 配置中包含一个自动生成的模式视图
# api/urls.py from rest_framework.schemas import get_schema_view schema_view = get_schema_view(title='LocalHost API') urlpatterns = [ ..., url(r'^schema/$', schema_view), ]
- API 文档
# urls.py from django.conf.urls import url, include from rest_framework.documentation import include_docs_urls urlpatterns = [ ..., url(r'api/docs/', include_docs_urls(title='API Documentation')), # 文档 url ]
完整的项目文档,请参考 GitHub https://github.com/lichaoxiang/My-Django-REST-Framework
参考文档
http://www.django-rest-framework.org/
原创文章,转载请注明出处:http://www.opcoder.cn/article/9/