体验Django REST framework,解读REST架构风格

栏目: Python · 发布时间: 6年前

内容简介:因为项目中使用了REST API,所以对REST架构风格做了一些研究。如果有对REST架构风格还不了解,或者一知半解的朋友,可以读读我的另一篇文章《一开始在项目中使用的是OpenResty来实现REST API,但使用起来一直觉得不方便。主要是因为Lua没有ORM,也没有REST架构风格的框架。直到最近在用Django时,接触到Django REST framework,在深感便利的同时,也进一步加深了对REST架构风格的理解。所以写下这篇文章,一方面记录Django REST framework的体验过

因为项目中使用了REST API,所以对REST架构风格做了一些研究。如果有对REST架构风格还不了解,或者一知半解的朋友,可以读读我的另一篇文章《 那些年,我们一起误解过的REST 》。

一开始在项目中使用的是OpenResty来实现REST API,但使用起来一直觉得不方便。主要是因为 Lua 没有ORM,也没有REST架构风格的框架。直到最近在用Django时,接触到Django REST framework,在深感便利的同时,也进一步加深了对REST架构风格的理解。所以写下这篇文章,一方面记录Django REST framework的体验过程,同时借此解读下REST架构风格。

1. 体验Django REST framework

1.1 安装

pip install django
pip install djangorestframework

1.2 创建Django项目并初始化

django-admin startproject rest_example  # 创建Django项目
django-admin.py startapp app    # 创建应用
python manage.py migrate    # 执行迁移
python manage.py createsuperuser --email admin@example.com --username admin # 创建超级用户

1.3 项目配置

在项目INSTALL_APP配置中加入rest_framework,修改rest_example/settings.py。

INSTALLED_APPS = (
    ...
    'rest_framework',
)

1.4 REST framework配置

在项目配置中加入REST_FRAMEWORK配置,在rest_example/settings.py加入以下内容。

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}

1.5 创建序列化器

创建rest_example/app/serializers.py文件,内容如下。

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')

序列化器会自动将模型序列化。对于RESTful架构来说,超链模型序列化器是非常合适的,因为可以提供连通性。

1.6 创建视图

修改rest_example/app/views文件,内容如下。

from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_example.app.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

ViewSet封装了通用的视图,实现了get、post、put、delete等请求方法对应的通用处理方法,直接继承可以极大地简化代码。

1.7 配置路由

修改rest_example/urls文件,内容如下。

from django.conf.urls import url, include
from rest_framework import routers
from rest_example.app 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-auth路由是用于对REST API进行鉴权。

1.8 大功告成

启动Django,在浏览器中访问http://127.0.0.1:8000/,可以看到如下图所示界面。

image.png

只通过简单的配置,就得到了一个完善的REST API,可谓相当的便利。

2. 解读REST架构风格

2.1 资源URI

先看最简单的资源GET /,响应如下。

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "users": "http://127.0.0.1:8000/users/",
    "groups": "http://127.0.0.1:8000/groups/"
}

上述响应表示存在两种资源(可引用的对象):user资源和group资源,其URI分别为http://127.0.0.1:8000/users/和http://127.0.0.1:8000/groups/。

REST是面向资源的架构,在REST中,URI代表某个或某种资源,所以 URI中只能有名词,而且一般是复数形式

再看user资源GET /users,响应如下。

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "url": "http://127.0.0.1:8000/users/1/",
        "username": "admin",
        "email": "admin@example.com",
        "groups": []
    }
]

上述响应表示当前只有一个user资源,用户名是admin,对应的URI是http://127.0.0.1:8000/users/1/。

因为URI表示的是具体的资源,所以应该在URI中包含user id。假如写为http://127.0.0.1:8000/users?id=1,这样代表的是从所有的user资源中过滤出id=1的资源集合,而不是表示id=1的具体资源。

在资源URI中,id需要放在URI路径中,不能放在请求参数中。请求参数适用于放过滤条件、分页信息等内容。

2.2 连通性

在GET /请求的响应中,包含了user资源和对应group资源的URI。

在GET /users请求的响应中,也包含了groups资源,只是因为当前没有group资源,所以是空数组。我们在页面登录后,创建名称为superuser的group,再把admin用户加入到superuser组中。此时再请求GET /users,响应如下。

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "url": "http://127.0.0.1:8000/users/1/",
        "username": "admin",
        "email": "admin@example.com",
        "groups": [
            "http://127.0.0.1:8000/groups/1/"
        ]
    }
]

可以看到,groups数组表明admin用户只属于一个组,该group资源对应的URI为http://127.0.0.1:8000/groups/1/。如果需要了解该group资源的具体信息,则可以通过请求GET http://127.0.0.1:8000/groups/1获取。

在资源响应中包含关联资源的URI,可以提供后续操作的入口,将各种资源串联起来,便于客户端进行下一步操作。

2.3 统一请求方法

REST通过统一请求方法,只知道资源URI就可以进行一系列增删查改的操作。反应到页面上,在GET /users资源时,页面可以提供如下页面来创建一个新的user资源,而这一切都是因为约定了POST是创建操作,资源描述通过body传递,资源ID由服务器自动生成,新生成资源的URI会通过请求响应返回。

image.png

同时,因为统一了请求方法,并且在Header中声明了该资源支持的请求方法,所以页面可以针对该资源,提供增删查改的一系列操作入口。如下图右上角所示。

image.png

2.4 资源的表述

在《 那些年,我们一起误解过的REST 》文中我提到过,同一个资源可以有多个不同的表述,每个表述需要是自描述的。例如,请求GET /users/1,可以选择返回json格式还是api格式,如下图右上角所示。

image.png

当请求json格式时,REST API返回纯json的表述;当请求api格式(实际上是html格式)时,REST API返回渲染过的html页面,所以才有上文的各种功能丰富的截图。这两种表述都是对相同资源的表述,本质上是相同的。至于究竟返回的是什么格式的表述,则需要通过响应Header中的Content-type字段说明。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design Accessible Web Sites

Design Accessible Web Sites

Jeremy Sydik / Pragmatic Bookshelf / 2007-11-05 / USD 34.95

It's not a one-browser web anymore. You need to reach audiences that use cell phones, PDAs, game consoles, or other "alternative" browsers, as well as users with disabilities. Legal requirements for a......一起来看看 《Design Accessible Web Sites》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具