REST是所有Web应用都应该遵守的架构设计指导原则。

Representational State Transfer,翻译是”表现层状态转化”。

REST核心: 资源, 状态转移, 统一接口

资源: 是REST最明显的特征,是指对某类信息实体的抽象,资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。

状态转移: 是指客户端痛服务端进行交互的过程中,客户端能够通过对资源的表述,实现操作资源的目的

统一接口: REST要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。 比如,客户端通过HTTP的4个请求方式(POST, GET, PUT, PATCH)来操作资源,也就意味着不管你的url是什么,不管请求的资源是什么但操作的资源接口都是统一的。

GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT(PATCH)用来更新资源,DELETE用来删除资源。

 

一.django中使用restful

1.安装相关库

pip install djangorestframework==3.4.6
pip install django-filter # 用于过滤

 

2.settings.py配置的修改

在工程目录中的settings.py文件的INSTALLED_APPS中需要添加rest_framework

INSTALLED_APPS = [
...

  'rest_framework',
]

 

3.在应用app中定义路由URL

定义路由需要注意:

  1. 使用router.register注册的url为资源,而且资源只能为名词不能为动词。

  2. 定义的资源不要加'/'斜杠,在访问地址的时候,URL中会默认的添加反斜杠'/'

    from django.conf.urls import url
     
     from rest_framework.routers import SimpleRouter
     
     from app import views
     
     # 引入路由
     router = SimpleRouter()
     # 使用router注册的地址
     router.register(r'^student', views.StudentView)
     
     urlpatterns = [
     
     ]
     urlpatterns += router.urls

     

4.在视图views.py文件中定义StudentView类

具体的详细介绍在地址

通过定义StudentView并继承了mixins的方法,即可有对应个增删改查的方法。在StudentView中还定义了两个变量queryset、serializer_class。

from rest_framework import viewsets, mixins
​
from app.models import Student
from app.serializers import StudentSerializer
​
​
class StudentView(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  mixins.DestroyModelMixin,
                  mixins.RetrieveModelMixin,
                  mixins.UpdateModelMixin,
                  viewsets.GenericViewSet):
​
    # 返回数据
    queryset = Student.objects.all()  # 需要需要序列化的数据
    # 序列化结果
    serializer_class = StudentSerializer  #指定序列化的类(需自己定义)

其中queryset参数表示需要需要序列化的数据 serializer_class参数指定序列化的类

 

5.定义序列化类

序列化类需要继承ModelSerializer,使用ModelSerializer表明序列化整个Student模型,并且可以指定虚拟化哪些字段。

from rest_framework import serializers
​
from app.models import Student
​
class ArticleSerializer(serializers.ModelSerializer):
    # 序列化时,创建资源需对传入的字段进行校验
    title = serializers.CharField(required=True, max_length=10, min_length=5,
                                  error_messages={
                                    'required': '标题必填',
                                    'max_length':'最大长度10',
                                    'min_length':'最小长度5'})
    desc = serializers.CharField(required=False)
    
    class Meta:
        # 指定序列化的模型
        model = Article
        # 指定序列化哪些字段
        fields = ['title','desc','id','is_show'] # 展示的字段,指定序列化后才能展示
        
   #进一步校验
    def validate(self, attrs):
        # 校验文章标题是否重复
        title = attrs.get('title')
        if title:
            if Article.objects.filter(title=title).exists():
                raise ParamsException({'code':1002, 'msg':'标题重复'})
        return attrs      
    # 父类默认调用
    # 将字段定义的值,改成我们想要展示的值(例: is_show的值true变成中文 '展示')
    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['is_show'] = '展示' if data['is_show'] else '不展示'
        return data

通过以上的代码,可以通过以下的URL和HTTP请求方式,完成对资源Student的CRUD操作:

CRUD对应的增删改查:

增: POST http://127.0.0.1:8080/stu/addStu/

删: DELETE http://127.0.0.1:8080/stu/addStu/1/

改: UPDATE http://127.0.0.1:8080/stu/addStu/1/

查: GET http://127.0.0.1:8080/stu/addStu/1/

 

二.rest响应重构

1.修改响应结构

1.修改settings.py中的返回数据结构的配置信息
# rest_framework 使用相关配置
REST_FRAMEWORK = {
    # 分页配置    分页配置只需在setting中设置就ok
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 3,  # 每页几条数据
    
    #过滤配置     根据条件来查找数据
    'DEFAULT_FILTER_BACKENDS':(
        'django_filters.rest_framework.DjangoFilterBackend',
    ),
    
    这里修改返回数据结构的配置信息
    # render的配置 响应时自动调用render方法,将字典转化为json数据
    'DEFAULT_RENDERER_CLASSES':(
        'utils.renderer.MyJsonRenderer',
    )
​
}

注意: 定义default_renderer_classes参数,指定render的时候使用我们自定义的renderer.py文件中的CustomJsonRenderer类方法

2.重构JSONRenderer下的render方法

该方法继承了JSONRenderer并且重构了render方法,修改了返回的数据结构

class CustomJsonRenderer(JSONRenderer):

    def render(self, data, accepted_media_type=None, renderer_context=None):

        if isinstance(data, dict):
            msg = data.pop('msg', '请求成功')
            code = data.pop('code', 0)
        else:
            msg = '请求成功'
            code = 0
     # 将http响应状态码改为200, 若不加,抛错时,http的响应状态码会显示500,
     # 前端ajax请求信息会是失败,不会进入then,直接执行catch里的语句
        response = renderer_context['response']
        response.status_code = 200

        res = {
            'code': code,
            'msg': msg,
            'data': data
        }

        return super().render(res, accepted_media_type, renderer_context)

 

2.异常的响应的结构

自定义异常处理,一定需要继承from rest_framework.exceptions import APIException 中的APIException,在编写自己的异常处理的方法

 

三.分页

修改settings.py配置文件

只需 在rest_framework配置中,增加分页的配置信息

REST_FRAMEWORK = {
    # 分页配置    分页配置只需在setting中设置就ok
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 3,  # 每页几条数据
}

注意:在结果在data对应的value值中,有一个count的key,表示返回数据有3条,next表示下一个的url,previous表示上一页的url。

四.过滤

修改settings.py配置文件,增加filter过滤的信息

1.安装过滤的库

pip install django-filter

2. 配置setings.py的信息

配置DEFAULT_FILTER_BACKENDS

django2.0以下版本的配置
REST_FRAMEWORK = {
    # 分页配置    
    .......
    
    #过滤配置     根据条件来查找数据
    'DEFAULT_FILTER_BACKENDS':(
        'rest_framework.filters.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
    ),
django2.0以上版本的配置
REST_FRAMEWORK = {
    # 分页配置  
    ........
    #过滤配置     根据条件来查找数据
    'DEFAULT_FILTER_BACKENDS':(
        'django_filters.rest_framework.DjangoFilterBackend',
    ),
}

 

3.views中指定filter_class

class ArticleView(viewsets.GenericViewSet,  # 提供两个方法
                  mixins.CreateModelMixin,  #创建
                  mixins.ListModelMixin,   #查看所有
                  mixins.DestroyModelMixin, #删除
                  mixins.RetrieveModelMixin, # 查看详情
                  mixins.UpdateModelMixin,  # 修改
                  ):
    # 资源对应所有数据,必须定义该参数,会被源码中get_queryset()方法调用,默认返回它
    queryset = Article.objects.all()
    # 序列化,必须定义该参数, 会被源码中get_serializer()方法调用
    serializer_class = ArticleSerializer
    # 过滤
    filter_class = ArticleFilter  #这里指定过滤调用的类

 

4.定义过滤的类

2.0以上版本
import django_filters
​
from app.models import Article
​
class ArticleFilter(django_filters.rest_framework.FilterSet):
    # 模糊查询title字段
    title = django_filters.CharFilter(lookup_expr='contains')
    desc = django_filters.CharFilter(lookup_expr='contains')
    # id_min和id_max为接口中定义的过滤参数,其对应到数据库中查询时,对应id字段
    id_min = django_filters.CharFilter('id',lookup_expr='gte')
    id_max = django_filters.CharFilter('id',lookup_expr='lt')
    # 老版本:method改写action
    is_show = django_filters.CharFilter(method='filter_is_show')
    class Meta:
        model = Article
        # 老版本中 fields中定义的参数,才是接口中能过滤的参数
        fields = ['title','desc','id', 'is_show']  # 高版本可不写全
def filter_is_show(self,queryset, name, value):
        if value == 'on':
            return queryset.filter(is_show=1)
        else:
            return queryset.filter(is_show=0)
2.0以下版本

继承的父类修改为: filters.FilterSet

import django_filters
from rest_framework import filters
​
class ArticleFilter(filters.FilterSet):
    ...