REST是所有Web应用都应该遵守的架构设计指导原则。
Representational State Transfer,翻译是”表现层状态转化”。
REST核心: 资源, 状态转移, 统一接口
资源: 是REST最明显的特征,是指对某类信息实体的抽象,资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。
状态转移: 是指客户端痛服务端进行交互的过程中,客户端能够通过对资源的表述,实现操作资源的目的
统一接口: REST要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。 比如,客户端通过HTTP的4个请求方式(POST, GET, PUT, PATCH)来操作资源,也就意味着不管你的url是什么,不管请求的资源是什么但操作的资源接口都是统一的。
GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT(PATCH)用来更新资源,DELETE用来删除资源。
pip install djangorestframework==3.4.6
pip install django-filter # 用于过滤
在工程目录中的settings.py文件的INSTALLED_APPS中需要添加rest_framework
INSTALLED_APPS = [
...
‘rest_framework‘,
]
定义路由需要注意:
使用router.register注册的url为资源,而且资源只能为名词不能为动词。
定义的资源不要加‘/‘斜杠,在访问地址的时候,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
具体的详细介绍在地址
通过定义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参数指定序列化的类
序列化类需要继承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_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文件中的MyJsonRenderer类方法
该方法继承了JSONRenderer并且重构了render方法,修改了返回的数据结构
class MyJsonRenderer(JSONRenderer): def render(self, data, accepted_media_type=None, renderer_context=None): # 重构方法一: # try: # code = data.pop(‘code‘) # msg = data.pop(‘msg‘) # except: # code = 200 # msg = ‘请求成功‘ # try: # result = data.pop(‘data‘) # except: # result = data # 重构方法二: ps: 实现原理都一样 code = data.pop(‘code‘, 200) msg = data.pop(‘msg‘, ‘请求成功‘) result = data.pop(‘data‘, data) # 将http响应状态码改为200, 若不加,抛错时,http的响应状态码会显示500,前端ajax请求信息会是失败,不会进入then,直接执行catch里的语句 renderer_context[‘response‘].status_code = 200 res = { ‘code‘: code, ‘msg‘: msg, ‘data‘: result, } return super().render(res,accepted_media_type=None, renderer_context=None)
自定义异常处理,一定需要继承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过滤的信息
pip install django-filter
配置DEFAULT_FILTER_BACKENDS
REST_FRAMEWORK = { # 分页配置 ....... #过滤配置 根据条件来查找数据 ‘DEFAULT_FILTER_BACKENDS‘:( ‘rest_framework.filters.DjangoFilterBackend‘, ‘rest_framework.filters.SearchFilter‘, ),
REST_FRAMEWORK = { # 分页配置 ........ #过滤配置 根据条件来查找数据 ‘DEFAULT_FILTER_BACKENDS‘:( ‘django_filters.rest_framework.DjangoFilterBackend‘, ), }
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 #这里指定过滤调用的类
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)
继承的父类修改为: filters.FilterSet
import django_filters from rest_framework import filters ? class ArticleFilter(filters.FilterSet): ...
?
原文:https://www.cnblogs.com/Deaseyy/p/10903347.html