一、Django Rest Framework
Django REST Framework(简称DRF),是一个用于构建Web API的强大且灵活的工具包。
先说说REST:REST是一种Web API设计标准,是目前比较成熟的一套互联网应用程序的API设计理论。REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。Fielding是一个非常重要的人,他是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。所以,他的这篇论文一经发表,就引起了关注,并且立即对互联网开发产生了深远的影响。
Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写。我对这个词组的翻译是”表现层状态转化”。如果一个架构符合REST原则,就称它为RESTful架构。所以简单来说,RESTful是一种Web API设计规范,根据产品需求需要定出一份方便前后端的规范,因此不是所有的标准要求都需要遵循。
学习RESTful API的资料:RESTful API 设计指南、理解RESTful架构
你可能想要使用REST Framework的一些理由:
- 基于Web可浏览的API能让你赢得更多开发者。
- 包含OAuth1a和OAuth2的认证机制。
- 序列化同时支持ORM和非ORM的数据源。
- 自定义,如果不想用更为强大的功能,可以只使用常规的函数视图。
- 大量的文档,牛叉的社区支持。
- 得到大公司使用和信任,比如Mozilla、Red Hat、Eventbrite都用它,靠谱~。
二、安装需求
REST框架具有以下要求:
- Python(2.7,3.2,3.3,3.4,3.5,3.6)
- Django(1.10,1.11,2.0 alpha)
下面的包是可选的:
- coreapi(1.32.0+) – 支持模式生成。
- Markdown(2.1.0+) – Markdown支持可浏览的API。
- django-filter(1.0.1+) – 过滤支持。
- django-crispy-forms – 改进的HTML显示过滤。
- django-guardian(1.1.1+) – 支持对象级别的权限控制。
三、安装配置
1. 使用pip
进行安装,包含那些你想要的可选包:
1 2 3 |
$ pip install djangorestframework $ pip install markdown # Markdown support for the browsable API. $ pip install django-filter # Filtering support |
2. 添加rest_framework
到settings.py的INSTALLED_APPS
1 2 3 4 |
INSTALLED_APPS = ( ... 'rest_framework', ) |
3. (可选)如果想要增加可浏览的API,你也将需要添加REST框架的login和logout视图;添加如下行到根urls.py
文件中。
1 2 3 4 |
urlpatterns = [ ... url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ] |
请注意,URL路径可以是任何你想要的,但你必须包括'rest_framework.urls'
与'rest_framework'
命名空间。你可以在Django 1.9+中省略命名空间,而REST框架将为你设置它。
四、使用示例
我们将创建一个简单的API来允许管理员用户查看和编辑系统中的用户和组。
创建一个名为的新Django项目tutorial,然后启动一个名为的新应用程序quickstart。
1 2 3 4 |
$ django-admin.py startproject tutorial $ cd tutorial $ django-admin.py startapp quickstart $ cd .. |
同步数据库,并且创建一个名为admin,密码为的初始用户password123。稍后在我们的示例中,我们将以用户身份进行身份验证。
1 2 3 |
$ python manage.py makemigrations $ python manage.py migrate $ python manage.py createsuperuser --username=admin --email=admin@admin.com |
然后要完成djangoframework安装配置。
Serializers
首先我们要定义一些序列化器,创建一个名为tutorial/quickstart/serializers.py的文件,将用于定义如何展示API的新模块。
1 2 3 4 5 6 7 8 9 10 11 12 |
from django.contrib.auth.models import User, Group from rest_framework import serializers class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = User fields = ('url', 'username', 'email', 'groups') class GroupSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Group fields = ('url', 'name') |
请注意,在这种情况下,我们使用超链接关系HyperlinkedModelSerializer(继承的类是HyperlinkedModelSerializer)。你也可以使用ModelSerializer继承,但超链接是一个很好的RESTful设计。
Views
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from django.contrib.auth.models import User, Group from rest_framework import viewsets from tutorial.quickstart.serializers import UserSerializer, GroupSerializer class UserViewSet(viewsets.ModelViewSet): """ API endpoint that allows users to be viewed or edited. """ queryset = User.objects.all().order_by('-date_joined') serializer_class = UserSerializer class GroupViewSet(viewsets.ModelViewSet): """ API endpoint that allows groups to be viewed or edited. """ queryset = Group.objects.all() serializer_class = GroupSerializer |
我们把所有常见的行为组合在一起,形成ViewSets视图集,而不是编写多个视图。如果需要的话,我们可以很容易地将这些视图分解成单独的视图,但是使用视图集使视图逻辑很好地组织,并且非常简洁。
URLs
最后可以编写URL,在tutorial/urls.py。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from django.conf.urls import url, include from rest_framework import routers from tutorial.quickstart import views router = routers.DefaultRouter() router.register(r'users', views.UserViewSet) router.register(r'groups', views.GroupViewSet) # Wire up our API using automatic URL routing. # Additionally, we include login URLs for the browsable API. urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ] |
因为我们使用视图集而不是视图,所以我们可以自动为我们的API生成URL conf,只需向routers类注册视图集即可(可以给Default.Router添加trailing_slash,用来控制URL反斜杠的,默认为True,表示/users/跟/users效果一样;如果为False时/users/访问会报错)。
同样,如果我们需要对API URL进行更多的控制,我们可以直接使用普通的基于类的视图,并明确地写入URL conf。
另外当我们使用viewsets.ModelViewSet超类时可以没有base_name参数,但是使用viewsets.ViewSet超类就必须要使用base_name参数。
1 2 |
router = routers.DefaultRouter(trailing_slash=True) router.register(r'users', UserViewSet, base_name='users') |
Settings
最后,djangoframework将包括默认的登录和注销视图,以便使用可浏览的API,这是可选的;但如果你的API需要身份验证,并且你想使用可浏览的API,则可以使用它。比如希望我们的API只能被管理员用户访问,设置模块将处于tutorial/settings.py。
所有REST框架的全局设置都被保存到一个叫做REST_FRAMEWORK的配置字典中。
1 2 3 4 5 6 7 8 9 10 11 |
INSTALLED_APPS = ( ... 'rest_framework', ) REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAdminUser', ], 'PAGE_SIZE': 10 } |
使用Django标准的’django.contrib.auth’权限,或者对未验证的用户使用只读权限。
1 2 3 4 5 |
REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' ] } |
测试API
准备测试我们建立的API,从命令行启动服务器。
1 |
$ python manage.py runserver |
现在可以在浏览器中输入http://127.0.0.1:8000/来打开API了。
并且可以查看所创建的全部’users’ API,直接点击url使用浏览器访问也行,或者使用postman工具。
或者使用curl或httpie来测试我们的API,Httpie是用Python编写的一个用户友好的http客户端,可以使用pip安装httpie。
1 2 |
$ pip install httpie $ http http://127.0.0.1:8000/ |
使用curl命令,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ curl -H 'Accept: application/json; indent=4' -u admin:admin http://127.0.0.1:8000/users/ [ { "url": "http://127.0.0.1:8000/users/1/", "username": "dkey", "email": "dkey@163.com", "is_staff": false }, { "url": "http://127.0.0.1:8000/users/2/", "username": "admin", "email": "admin@admin.com", "is_staff": true } ] |
如果你使用管理员登录(需要创建一个管理员用户),那么现在就应该可以添加、创建和删除用户了。
五、再说Serializers与Views
前面我们那个Serializers用的是HyperlinkedModelSerializer超链接管理,views很简单。下面是一个标准的djangoframework Serializers/views,Serializers继承ModelSerializers类,映射模型字段。这里给了一个样例:
Models.py
1 2 3 4 5 6 7 8 9 10 11 |
from django.db import models class VirtualHost(models.Model): hostname = models.CharField(verbose_name='Hostname', max_length=30, blank=True, null=True) ip = models.GenericIPAddressField(verbose_name='IP', blank=True, null=True) cpu = models.CharField(verbose_name='Cpu', max_length=30, blank=True, null=True) memory = models.CharField(verbose_name='Memory', max_length=30, blank=True, null=True) class Meta: db_table = 'host' |
serializers.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
from rest_framework.serializers import ModelSerializer from rest_framework import serializers from api.models import VirtualHost class VirtualHostCreateSerializer(ModelSerializer): class Meta: model = VirtualHost fields = ('hostname', 'ip', 'cpu', 'memory') class VirtualHostListSerializer(ModelSerializer): class Meta: model = VirtualHost fields = ('hostname', 'ip', 'cpu', 'memory') class VirtualHostDetailSerializer(ModelSerializer): class Meta: model = VirtualHost fields = ('hostname', 'ip', 'cpu', 'memory') |
views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
from django.shortcuts import render from rest_framework.viewsets import ModelViewSet from rest_framework import viewsets from rest_framework.response import Response from rest_framework import status from .serializers import * from .models import VirtualHost class VirtualHostViewSet(ModelViewSet): def create(self, request, *args, **kwargs): self.serializer_class = VirtualHostCreateSerializer data = request.data.dict() serial = VirtualHostCreateSerializer(data=data) if not serial.is_valid(): return Response(status=status.HTTP_400_BAD_REQUEST) serial.save() return Response(serial.data) def destroy(self, request, *args, **kwargs): pass def update(self, request, *args, **kwargs): pass def list(self, request, *args, **kwargs): self.serializer_class = VirtualHostListSerializer self.queryset = VirtualHost.objects.all() return super(VirtualHostViewSet, self).list(request) def retrieve(self, request, *args, **kwargs): pk = kwargs.get('pk', 1) self.serializer_class = VirtualHostDetailSerializer self.queryset = VirtualHost.objects.filter(pk=pk) return super(VirtualHostViewSet, self).retrieve(request) def partial_update(self, request, *args, **kwargs): self.update(request, *args, **kwargs) |
这里定义的create、destroy、update、list、retrieve方法都是djangoframework默认已经有的。并且不同的调用方式,djangoframework会使用不同的方法(我们这里定义就是重写这些方法,方法名称一定要一致),这些也是API常用的方法。所以我们在定义接口视图时,可能会有不同的业务逻辑,但是接口操作方式基本就这么几种了;根据自己的业务逻辑去重写这些方法即可。
另外也可以根据已有的方法添加新方法,比如partial_update方法,做部分更新使用的。继承了update方法。
六、官方教程
本教程将引导熟悉REST框架创建每一部分。学习它需要一些时间,但是它会让你对每一部分如何相互匹配在一起邮个全方位的了解,强烈建议读一下。
- 1 – 序列化(Serialization)
- 2 – 请求和响应(Requests and Responses)
- 3 – 基于类的视图(Class-based Views)
- 4 – 身份验证和权限(Authentication & Permissions)
- 5 – 关系与超链接API(Relationships & Hyperlinked APIs)
- 6 – 视图集合与路由(ViewSets & Routers)
- 7 – 架构与客户端库(Schemas & client libraries)
为了测试的目的,有一个完整的教程API的实例API,可以在这里找到。
另外也可以看:
- Django REST framework的各种技巧——1.基础讲解
- Django REST framework的各种技巧——2.serializer
- Django REST framework的各种技巧——3.权限
- Django REST framework的各种技巧——4.Generic View
- Django REST framework的各种技巧——5.搜索
- Django REST framework的各种技巧——6.异常处理
- Django REST framework的各种技巧——7.导入导出