一、什么是restful?

REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”、
REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

二、restful API设计(规范)

一、API与用户的通信协议,总是使用HTTPS协议
二、域名https:api.zhangjianping.com     尽量将API部署在专用的域名(不存在跨域问题)https:zhangjianping.org/api      简单的API
三、版本URL:   https:api.zhangjianping.com/v1请求头           跨域时,引发发送多次请求
四、路径,网络上的东西都是资源,均使用名词去表示
五、methodGET:从服务器取出资源(一项或者是多项)POST:在服务器新建一个资源PUT:在服务器更新资源(客户端提供改变后的完整资源)PATCH:在服务器更新资源(客户端提供改变的属性)DELETE:从服务器删除资源
六、过滤通过在url上传参的形式传递搜索条件
七、状态码
八、错误处理
九、返回结果十、Hypermedia API,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

状态码附录

三、基于Django实现

路由系统:

urlpatterns = [url(r'^admin/', admin.site.urls),url(r'^users/$',views.User.as_view()),
]

CBV视图:

from django.http import JsonResponse
from django.views import View
class User(View):def get(self,request,*args,**kwargs):result = {"status":True,"data":"response data"}return JsonResponse(result,status=200)def post(self,request,*args,**kwargs):result = {"status":True,"data":"response data"}return JsonResponse(result,status=200)

四、基于Django-Rest-Framework框架实现

1、基本流程

路由系统:

from django.conf.urls import url
from django.contrib import admin
from app01 import viewsurlpatterns = [url(r'^test/$',views.TestView.as_view())
]

CBV视图:

from rest_framework.views import APIView
from rest_framework.response import Responseclass TestView(APIView):def dispath(self,request,*args,**kwargs):    """请求到来之后,都要执行dispatch方法,dispatch方法根据请求方式不同触发不同的函数来处理"""return super().dispatch(request,*args,**kwargs)def get(self,request,*args,**kwargs):return Response("GET请求,响应内容")def post(self,request,*args,**kwargs):return Response("POST请求,响应内容")def put(self,request,*args,**kwargs):return Response("PUT请求,响应内容")

以上这段代码就是rest framework框架的基本流程,重要的功能都是在APIView中的dispatch中触发的

当你运行上段代码会报错:

你使用的是restframework,但是模板用的却是Django的,所以报错在所难免,解决的办法就是在配置文件中注册

2、认证和授权

路由系统

from django.conf.urls import url
from django.contrib import admin
from app01 import viewsurlpatterns = [url(r'^test/$',views.TestView.as_view())
]

CBV视图:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BaseAuthentication
from rest_framework.request import Request
from rest_framework import exceptionstoken_list = ["zhangjianping",           #可以授权的数据
]class TestAuthentication(BaseAuthentication):def authenticate(self, request):'''用户认证,认证成功后返回元组:param request::return:'''val = request.query_params.get("token")    #get请求从网址栏获取到的数据if val not in token_list:                  #判断当前url是否可以授权访问raise exceptions.AuthenticationFailed("用户认证失败")return ("登录用户,","用户token")def authenticate_header(self, request):passclass TestView(APIView):'''调用这个函数的时候,会自动触发authentication_classes的运行,所以会先执行上边的类'''authentication_classes = [TestAuthentication,]permission_classes = []
def get(self,request,*args,**kwargs):print("====request.user====",request.user)         #当前登录的用户print("====request.auth====",request.auth)         #获取到的用户tokenreturn Response("GET请求,响应内容")def post(self,request,*args,**kwargs):return Response("POST请求,响应内容")def put(self,request,*args,**kwargs):return Response("PUT请求,响应内容")

3、用户登录

路由系统:

from django.conf.urls import url
from django.contrib import admin
from app01 import viewsurlpatterns = [url(r'^auth/$',views.AuthView.as_view()),
]

model表操作:

from django.db import modelsclass UserInfo(models.Model):username = models.CharField(max_length=16)password = models.CharField(max_length=16)token = models.CharField(max_length=64,null=True)

CBV视图:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BaseAuthentication
from rest_framework.request import Request
from rest_framework import exceptions
import time,hashlib
from app01 import modelsclass AuthView(APIView):authentication_classes = []def get(self,request):ret = {"code":1000,"msg":None}user = request.query_params.get("user")pwd = request.query_params.get("pwd")obj = models.UserInfo.objects.filter(username=user,password=pwd).first()if not obj:    #如果没有获取到用户信息执行ret["code"] = 1001ret["msg"] = "用户名或密码错误"return Response(ret)ctime = time.time()   #得到一个时间戳key = "%s|%s"%(user,ctime)    #类似于加密盐m = hashlib.md5()m.update(key.encode("utf-8"))token = m.hexdigest()        #token经过MD5加密处理obj.token = token            #数据库的空字符串,颁发授权信息ret["token"] = token         #写入数据表return Response(ret)

4、限制访问频率

路由系统

from django.conf.urls import url
from django.contrib import admin
from app01 import views
from app02 import views as app02_view
from app03 import views as app03_view
urlpatterns = [
rl(r'^salary/', app02_view.SalaryView.as_view()),url(r'^limit/', app03_view.LimitView.as_view()),
]

#配置文件REST_FRAMEWORK = {'UNAUTHENTICATED_USER': None,'UNAUTHENTICATED_TOKEN': None,"DEFAULT_AUTHENTICATION_CLASSES": [# "app02.utils.MyAuthentication",
    ],'DEFAULT_PERMISSION_CLASSES':[],'DEFAULT_THROTTLE_RATES':{'wdp':'2/minute'           #每分钟两次
    }
}CACHES = {'default': {'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache','LOCATION': 'cache',        数据默认报错在缓存}
}

#生写,自己实现            -----CBV视图
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.throttling import BaseThrottle,SimpleRateThrottlefrom rest_framework import exceptionsRECORD = {}
class MyThrottle(BaseThrottle):def allow_request(self,request,view):"""# 返回False,限制# 返回True,通行:param request: :param view: :return: """"""a. 对匿名用户进行限制:每个用户1分钟允许访问10次- 获取用户IP request 1.1.1.1"""import timectime = time.time()          #获取当前时间ip = self.get_ident(request)        #获取IPif ip not in RECORD:         #IP没有在新建的那个字典RECORD[ip] = [ctime,]    #将当前的IP作为key,时间作为value列表else:# [4507862389234,3507862389234,2507862389234,1507862389234,]time_list = RECORD[ip]         #如果在的话获取IP时间列表while True:val = time_list[-1]        #取出最后一个值if (ctime-60) > val:       #如果当前的时间-60秒>取出的最后一个值time_list.pop()        #就将这个值取出来else:breakif len(time_list) > 10:    #一分钟访问次数超过10次,return Falsereturn Falsetime_list.insert(0,ctime)    #将当前时间插入到第一个位置return Truedef wait(self,request):""":return: 返回需要等待的时间"""import timectime = time.time()first_in_time = RECORD[self.get_ident(request)][-1]wt = 60 - (ctime - first_in_time)      #等待的时间return wtclass LimitView(APIView):authentication_classes = []permission_classes = []throttle_classes=[MyThrottle,]def get(self,request,*args,**kwargs):# self.dispatchreturn Response('控制访问频率示例')def throttled(self, request, wait):"""If request is throttled, determine what kind of exception to raise."""class MyThrottled(exceptions.Throttled):default_detail = '请求被限制.'extra_detail_singular = 'Expected available in {wait} second.'extra_detail_plural = '还需要再等待{wait}'raise MyThrottled(wait)

CBV路由系统

class MySimpleRateThrottle(SimpleRateThrottle):scope = "wdp"def get_cache_key(self, request, view):return self.get_ident(request)
class LimitView(APIView):authentication_classes = []permission_classes = []throttle_classes=[MySimpleRateThrottle,]def get(self,request,*args,**kwargs):# self.dispatchreturn Response('控制访问频率示例')def throttled(self, request, wait):"""If request is throttled, determine what kind of exception to raise."""class MyThrottled(exceptions.Throttled):default_detail = '请求被限制.'extra_detail_singular = 'Expected available in {wait} second.'extra_detail_plural = '还需要再等待{wait}'raise MyThrottled(wait)

认证、权限+访问控制的实现

from django.conf.urls import url
from django.contrib import admin
from app04 import views as app04_viewurlpatterns = [url(r'^index/', app04_view.IndexView.as_view()),url(r'^manage/', app04_view.ManageView.as_view()),
]

setting配置

REST_FRAMEWORK = {'UNAUTHENTICATED_USER': None,'UNAUTHENTICATED_TOKEN': None,"DEFAULT_AUTHENTICATION_CLASSES": [    #认证控制# "app02.utils.MyAuthentication",
    ],'DEFAULT_PERMISSION_CLASSES':[     #权限控制
],'DEFAULT_THROTTLE_RATES':{'wdp_anon':'5/minute',       #匿名用户配置'wdp_user':'10/minute',      #正常用户配置
}
}CACHES = {                        #缓存配置'default': {'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache','LOCATION': 'cache',}
}

CBV视图

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
from rest_framework.authentication import BaseAuthentication
from app02 import modelsclass MyAuthentication(BaseAuthentication):"""用户认证类,获取url传过来的数据"""def authenticate(self, request):token = request.query_params.get('token')obj = models.UserInfo.objects.filter(token=token).first()if obj:return (obj.username,obj)return Nonedef authenticate_header(self, request):passclass MyPermission(object):message = "无权访问"def has_permission(self,request,view):if request.user:return Truereturn Falseclass AdminPermission(object):message = "无权访问"def has_permission(self,request,view):if request.user == 'alex':return Truereturn Falseclass AnonThrottle(SimpleRateThrottle):"""针对匿名用户的配置"""scope = "wdp_anon"      #配置文件中的值def get_cache_key(self, request, view):# 返回None,表示我不限制# 登录用户我不管if request.user:          #正常登陆的用户不做限制return None# 匿名用户                #匿名用户做限制return self.get_ident(request)class UserThrottle(SimpleRateThrottle):"""针对已经登陆的用户所做的配置"""scope = "wdp_user"     #配置文件获取def get_cache_key(self, request, view):# 登录用户if request.user:return request.user# 匿名用户我不管return None# 无需登录就可以访问
class IndexView(APIView):authentication_classes = [MyAuthentication,]          #用户认证permission_classes = []                               #无需登陆就可以访问的页面不需要权限的控制throttle_classes=[AnonThrottle,UserThrottle,]         #限流def get(self,request,*args,**kwargs):# self.dispatchreturn Response('无需登陆访问首页')  
  def throttled(self, request, wait):    """自定义返回的文本信息"""     class MyThrottled(exceptions.Throttled):        default_detail = '请求被限制.'        extra_detail_singular = 'Expected available in {wait} second.'        extra_detail_plural = '还需要再等待{wait}'     raise MyThrottled(wait)
# 需登录就可以访问
class ManageView(APIView):authentication_classes = [MyAuthentication,]permission_classes = [MyPermission,]                #需要登陆访问的页面做了权限的控制throttle_classes=[AnonThrottle,UserThrottle,]def get(self,request,*args,**kwargs):# self.dispatchreturn Response('需要登陆访问首页')

5、版本限制

URL做版本限制

urlpatterns = [url(r'^api/(?P<version>[v1|v2]+)/', include('api.urls')),]
urlpatterns = [url(r'^users/', views.UsersView.as_view(),name='u'),]

class UsersView(APIView):# 基于url传参# versioning_class = QueryParameterVersioning             get视图中直接采用request.version就可以取值# 基于URL http://127.0.0.1:8001/api/v2/users/# versioning_class = URLPathVersioning# 基于子域名 http://v1.luffy.com/users/# versioning_class = HostNameVersioning#上边的这些配置是基于局部配置,用的更多的是全局的配置,所以只介绍全局配置  

def get(self,request,*args,**kwargs):self.dispatchprint(request.version) # QueryParameterVersioning().detemiin_version()print(request.versioning_scheme) # QueryParameterVersioning()# 当前版本一样的URLurl = request.versioning_scheme.reverse(viewname='u',request=request)print(url)# 当前版本不一样的URLfrom django.urls import reverseurl = reverse(viewname='u',kwargs={'version':'v2'})print(url)return Response('...')

REST_FRAMEWORK = {'VERSION_PARAM':'version',          #固定的名字'DEFAULT_VERSION':'v1',              #默认版本号'ALLOWED_VERSIONS':['v1','v2'],       #可以使用的版本号'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning"     #版本由url控制}

hostname做版本控制

urlpatterns = [
     url(r'^api/', include('api.urls')),]
urlpatterns = [url(r'^users/', views.UsersView.as_view(),name='u'),]

class UsersView(APIView):def get(self,request,*args,**kwargs):self.dispatchprint(request.version) # QueryParameterVersioning().detemiin_version()print(request.versioning_scheme) # QueryParameterVersioning()

REST_FRAMEWORK = {'VERSION_PARAM':'version','DEFAULT_VERSION':'v1','ALLOWED_VERSIONS':['v1','v2'],'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"     #根据域名做版本控制}
根据hostname做版本限制需要配置域名,这里我们直接修改电脑的host文件做测试(Windows系统的 C:\Windows\System32\drivers\etc;mac本或者Linux的在# vim /etc/hosts)
直接做以下配置:127.0.0.1    v1.qqq.com127.0.0.1    v2.qqq.com

6、解析器

请求的数据进行解析:请求体进行解析。表示服务端可以解析的数据格式的种类。Content-Type: application/url-encoding.....request.bodyrequest.POSTContent-Type: application/json.....request.bodyrequest.POST
假如客户端发送的数据是:Content-Type: application/json'{"name":"alex","age":123}'
那么服务端接受的是:读取客户端发送的Content-Type的值 application/jsonparser_classes = [JSONParser,]media_type_list = ['application/json',]如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据

单视图:
class UsersView(APIView):parser_classes = [JSONParser,]全局配置:
REST_FRAMEWORK = {'VERSION_PARAM':'version','DEFAULT_VERSION':'v1','ALLOWED_VERSIONS':['v1','v2'],# 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",'DEFAULT_PARSER_CLASSES':['rest_framework.parsers.JSONParser',            #解析jsonparser'rest_framework.parsers.FormParser',            #解析formparser]}

7、序列化操作

#需要导入的包和模块
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BasicAuthentication
from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning,HostNameVersioning
from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer
from rest_framework.parsers import JSONParser,FormParser
from rest_framework.request import Request
from rest_framework import serializers
from . import models                    #数据表

数据库表

from django.db import models# Create your models here.class Menu(models.Model):name = models.CharField(max_length=32)class Group(models.Model):title = models.CharField(max_length=32)mu = models.ForeignKey(to="Menu",default=1)class UserInfo(models.Model):name = models.CharField(max_length=32)pwd = models.CharField(max_length=32)group = models.ForeignKey(to='Group')roles = models.ManyToManyField(to='Role')class Role(models.Model):name = models.CharField(max_length=32)

a、基本操作

class UsersSerializer(serializers.Serializer):name = serializers.CharField()pwd = serializers.CharField()class UsersView(APIView):def get(self,request,*args,**kwargs):self.dispatch# 方式一:# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")# return Response(user_list)# 方式二之多对象# user_list = models.UserInfo.objects.all()# ser = UsersSerializer(instance=user_list,many=True)# return Response(ser.data)# 方式二之单对象user = models.UserInfo.objects.all().first()ser = UsersSerializer(instance=user, many=False)return Response(ser.data)

b、跨表操作

class UsersSerializer(serializers.Serializer):name = serializers.CharField()pwd = serializers.CharField()group_id = serializers.CharField()xxxx = serializers.CharField(source="group.title")x1 = serializers.CharField(source="group.mu.name")class UsersView(APIView):def get(self,request,*args,**kwargs):self.dispatch# 方式一:# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")# return Response(user_list)# 方式二之多对象user_list = models.UserInfo.objects.all()ser = UsersSerializer(instance=user_list,many=True)return Response(ser.data)

c、复杂的序列化

操作一

class MyCharField(serializers.CharField):def to_representation(self, value):data_list = []for row in value:data_list.append(row.name)return data_listclass UsersSerializer(serializers.Serializer):name = serializers.CharField() # obj.namepwd = serializers.CharField()  # obj.pwdgroup_id = serializers.CharField() # obj.group_idxxxx = serializers.CharField(source="group.title") # obj.group.titlex1 = serializers.CharField(source="group.mu.name") # obj.mu.name# x2 = serializers.CharField(source="roles.all") # obj.mu.namex2 = MyCharField(source="roles.all") # obj.mu.name

操作二

class MyCharField(serializers.CharField):def to_representation(self, value):return {'id':value.pk, 'name':value.name}class UsersSerializer(serializers.Serializer):name = serializers.CharField() # obj.namepwd = serializers.CharField()  # obj.pwdgroup_id = serializers.CharField() # obj.group_idxxxx = serializers.CharField(source="group.title") # obj.group.titlex1 = serializers.CharField(source="group.mu.name") # obj.mu.name# x2 = serializers.CharField(source="roles.all") # obj.mu.namex2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name

操作三

class UsersSerializer(serializers.Serializer):name = serializers.CharField() # obj.namepwd = serializers.CharField()  # obj.pwdgroup_id = serializers.CharField() # obj.group_idxxxx = serializers.CharField(source="group.title") # obj.group.titlex1 = serializers.CharField(source="group.mu.name") # obj.mu.name# x2 = serializers.CharField(source="roles.all") # obj.mu.name# x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.namex2 = serializers.SerializerMethodField()def get_x2(self,obj):obj.roles.all()role_list = obj.roles.filter(id__gt=1)data_list = []for row in role_list:data_list.append({'pk':row.pk,'name':row.name})return data_list

以上三种方式都是使用相同的视图

class UsersView(APIView):def get(self,request,*args,**kwargs):self.dispatch# 方式一:# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")# return Response(user_list)# 方式二之多对象user_list = models.UserInfo.objects.all()# [obj1,obj2,obj3]ser = UsersSerializer(instance=user_list,many=True)return Response(ser.data)

d、基于model

class UsersSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"# fields = ['name', 'pwd','group']depth = 1class UsersView(APIView):def get(self,request,*args,**kwargs):self.dispatch# 方式一:# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")# return Response(user_list)# 方式二之多对象user_list = models.UserInfo.objects.all()# [obj1,obj2,obj3]ser = UsersSerializer(instance=user_list,many=True)return Response(ser.data)

e、生成url

class UsersSerializer(serializers.ModelSerializer):group = serializers.HyperlinkedIdentityField(view_name='detail')class Meta:model = models.UserInfofields = "__all__"fields = ['name', 'pwd','group']depth = 1class UsersView(APIView):def get(self,request,*args,**kwargs):self.dispatch# 方式一:# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")# return Response(user_list)# 方式二之多对象user_list = models.UserInfo.objects.all()# [obj1,obj2,obj3]ser = UsersSerializer(instance=user_list,many=True,context={'request':request})return Response(ser.data)

f、全局生成url

class UsersSerializer(serializers.HyperlinkedModelSerializer):class Meta:model = models.UserInfofields = "__all__"# fields = ['id','name','pwd']class UsersView(APIView):def get(self,request,*args,**kwargs):self.dispatch# 方式一:# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")# return Response(user_list)# 方式二之多对象user_list = models.UserInfo.objects.all()# [obj1,obj2,obj3]ser = UsersSerializer(instance=user_list,many=True,context={'request':request})return Response(ser.data)

请求数据验证

方式一

class PasswordValidator(object):def __init__(self, base):self.base = basedef __call__(self, value):if value != self.base:message = '用户输入的值必须是 %s.' % self.baseraise serializers.ValidationError(message)def set_context(self, serializer_field):"""This hook is called by the serializer instance,prior to the validation call being made."""# 执行验证之前调用,serializer_fields是当前字段对象passclass UsersSerializer(serializers.Serializer):name = serializers.CharField(min_length=6)pwd = serializers.CharField(error_messages={'required': '密码不能为空'}, validators=[PasswordValidator('666')])

方式二

class PasswordValidator(object):def __init__(self, base):self.base = basedef __call__(self, value):if value != self.base:message = '用户输入的值必须是 %s.' % self.baseraise serializers.ValidationError(message)def set_context(self, serializer_field):"""This hook is called by the serializer instance,prior to the validation call being made."""# 执行验证之前调用,serializer_fields是当前字段对象passclass UsersSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"extra_kwargs = {'name': {'min_length': 6},'pwd': {'validators': [PasswordValidator(666), ]}}

使用:

class UsersView(APIView):def get(self,request,*args,**kwargs):self.dispatch# 方式一:# user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")# return Response(user_list)# 方式二之多对象user_list = models.UserInfo.objects.all()# [obj1,obj2,obj3]ser = UsersSerializer(instance=user_list,many=True,context={'request':request})return Response(ser.data)def post(self,request,*args,**kwargs):ser = UsersSerializer(data=request.data)if ser.is_valid():print(ser.validated_data)else:print(ser.errors)return Response('...')

8、分页

a、基于limitoffsetpagination做分页

class P1(LimitOffsetPagination):max_limit = 3default_limit = 2limit_query_param = 'limit'offset_query_param = 'offset'

b、基于PageNumberPagination做分页

class P2(PageNumberPagination):# 每页显示的数据条数max_page_size = 5page_size = 2page_size_query_param = 'size'# 页码page_query_param = 'page'

c、基于CursorPagination做分页

class P3(CursorPagination):cursor_query_param = 'cursor'page_size = 2ordering = 'id'

需要用到的模块

from django.shortcuts import render
from rest_framework import views
from rest_framework.response import Response
from rest_framework.pagination import LimitOffsetPagination,PageNumberPagination,CursorPagination
from api import models
from api.serializers.index import IndexSerializer

基于视图实现

class IndexView(views.APIView):def get(self,request,*args,**kwargs):user_list = models.UserInfo.objects.all()            #查询到所有的数据p1 = P1()                                            #实例化显示的那个对象page_user_list = p1.paginate_queryset(queryset=user_list, request=request, view=self)     #经过处理后的数据列表ser = IndexSerializer(instance=page_user_list, many=True)       return Response(ser.data) # 不含上一页和下一页                 # return p1.get_paginated_response(ser.data) # 含上一页和下一页

基于视图使用对象的方式实现

class BaseResponse(object):def __init__(self,code=1000,data=None,error=None):self.code = codeself.data = dataself.error = error
class IndexView(views.APIView):def get(self,request,*args,**kwargs):ret = BaseResponse()              #基于对象的形式展示try:user_list = models.UserInfo.objects.all()p1 = P1()page_user_list = p1.paginate_queryset(queryset=user_list,request=request,view=self)ser = IndexSerializer(instance=page_user_list,many=True)ret.data = ser.data         #给对象赋值ret.next = p1.get_next_link()      #上一页下一页链接except Exception as e:ret.code= 1001ret.error = 'xxxx错误'return Response(ret.__dict__)           #以字典的形式返回

9、视图

1. APIView

class IndexView(views.APIView):def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all()ser = IndexSerializer(instance=user_list,many=True)return Response(ser.data)

2.GenericAPIView

class IndexView(generics.GenericAPIView):queryset = models.UserInfo.objects.all()serializer_class = IndexSerializerpagination_class = P2def get(self,request,*args,**kwargs):user_list = self.get_queryset()p1 = self.paginatordata = p1.paginate_queryset(queryset=user_list,request=request,view=self)ser = self.get_serializer(instance=data,many=True)return p1.get_paginated_response(ser.data)

3. GenericViewSet(ViewSetMixin, generics.GenericAPIView)

路由修改
urlpatterns = [url(r'^index/$', views.IndexView.as_view({'get':'list','post':'create'})),]from rest_framework.viewsets import GenericViewSet
class IndexView(GenericViewSet):queryset = models.UserInfo.objects.all()serializer_class = IndexSerializerpagination_class = P2def list(self,request,*args,**kwargs):print("这里是list请求")return Response("...")def retrieve(self,request,*args,**kwargs):print("这里是post请求")return Response("...")def create(self,request,*args,**kwargs):print("这里是put请求")return Response("...")自定义:增POST/users/删DELETE/users/1/改PUT/users/1/patch/users/1/查GET/users/ GET/users/1/urlpatterns = [url(r'^index/$', views.IndexView.as_view()),url(r'^index/(?P<pk>\d+)$', views.IndexView.as_view({'get':'retrieve'})),
]class IndexView(views.APIView):def get(self,request,*args,**kwargs):pk = kwargs.get('pk')if pk:pass # 获取单条信息else:pass # 获取列表信息def post(self,request,*args,**kwargs):passdef put(self,request,*args,**kwargs):passdef patch(self,request,*args,**kwargs):passdef delete(self,request,*args,**kwargs):pass

4.ModelViewSet

ModelViewSet(mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet)
视图:
urlpatterns = [url(r'^user/$',views.IndexView.as_view({"get":"list","post":"create"})),url(r'^user/(?P<pk>\d+)/$',views.IndexView.as_view({"get":"retrieve","delete":"destroy","put":"update","patch":"partial_update"}))
]
from rest_framework.viewsets import ModelViewSetclass IndexView(ModelViewSet):queryset = models.UserInfo.objects.all()serializer_class = IndexSerializerpagination_class = P2        

10、路由和渲染器

第一类:# http://127.0.0.1:8000/api/v1/auth/url(r'^auth/$', views.AuthView.as_view()),# http://127.0.0.1:8000/api/v1/auth.json # 想要让页面显示json格式url(r'^auth\.(?P<format>[a-z0-9]+)$', views.AuthView.as_view()),# http://127.0.0.1:8000/api/v1/auth/1/url(r'^auth/(?P<pk>\d+)/$', views.AuthView.as_view()),# http://127.0.0.1:8000/api/v1/auth/1.jsonurl(r'^auth/(?P<pk>\d+)\.(?P<format>[a-z0-9]+)$', views.AuthView.as_view()),class AuthView(views.APIView):def get(self,request,*args,**kwargs):return Response('...')

第二类:url(r'^index/$', views.IndexView.as_view({'get':'list','post':'create'})),url(r'^index/\.(?P<format>[a-z0-9]+)$', views.IndexView.as_view({'get':'list','post':'create'})),url(r'^index/(?P<pk>\d+)/$', views.IndexView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),url(r'^index/(?P<pk>\d+)\.(?P<format>[a-z0-9]+)$', views.IndexView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),class IndexView(viewsets.ModelViewSet):queryset = models.UserInfo.objects.all()serializer_class = IndexSerializerpagination_class = P2

第三类: router = DefaultRouter()router.register('index',views.IndexViewSet)urlpatterns = [url(r'^', include(router.urls)),]class IndexViewSet(viewsets.ModelViewSet):queryset = models.UserInfo.objects.all()serializer_class = IndexSerializerpagination_class = P2class IndexSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"

.渲染器
renderer_classes = [JSONRenderer,BrowsableAPIRenderer]     #好看的页面默认返回的是这两个,如果只想返回json则    JSONRenderer    

未完待续。。。。

转载于:https://www.cnblogs.com/52-qq/p/8417462.html

Django-Rest-Framework相关推荐

  1. 03 Django REST Framework 视图和路由

    01-DRF中的request 在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等. 比如,区别 ...

  2. Django REST framework 简介

    1.在序列化与反序列化时,虽然操作的数据不尽相同,但是执行的过程却是相似的,也就是说这部分代码是可以复用简化编写的. 2.在开发REST API的视图中,虽然每个视图具体操作的数据不同,但增.删.改. ...

  3. Django REST framework API 指南(2):响应

    Django REST framework API 指南(1):请求 Django REST framework API 指南(2):响应 Django REST framework API 指南(3 ...

  4. Django REST framework API 指南(12):验证器

    官方原文链接 本系列文章 github 地址 转载请注明出处 验证器 大多数情况下,您在 REST framework 中处理验证时,只需依赖默认的字段验证,或者在序列化类或字段类上编写明确的验证方法 ...

  5. Django REST framework的一些奇巧淫技(干货!!!)

    开始之前,假设你已经有Django和Django REST framework的一些基础了 mixins,ViewSet和routers配合使用 minxis的类有5种 CreateModelMixi ...

  6. Django REST framework快速入门

    1)简介: 接口使用REST framework,REST framework是一套基于Django 的 REST 框架,是一个强大灵活的构建 Web API 的工具包. 写接口三步完成:连接数据库. ...

  7. Django REST framework 1

    Django REST framework Django REST framework官方文档:点击  中文文档:点击 安装djangorestframework:pip3 install djang ...

  8. Django REST framework的各种技巧——1.基础讲解

    写在最上面的话 django是一个神奇的框架,而restframework又是遵循了这个框架的另一个神奇的框架,然而由于restframework的文档稀烂无比,很多时候你必须看源码才能写出科学的代码 ...

  9. 在django restful framework中设置django model的property

    众所周知,在django的model中,可以某些字段设置@property和setter deleter getter,这样就可以在存入数据的时候进行一些操作,具体原理请参见廖雪峰大神的博客https ...

  10. Django Rest Framework

    新的一年启程,大家又投入到紧张的学习和工作中,作为一个互联网人必须时刻紧跟科技发展的脚步.对于大火的 Python 编程语言我们怎么能错过,我们[51Reboot]这就为大家带来新年的第一堂 Pyth ...

最新文章

  1. 【组队学习】【35期】深入浅出Pytorch
  2. RecycleView 缓存原理解析
  3. IOS开发之自定义Button(集成三种回调模式)
  4. 汽车abs matlab仿真模糊pid控制
  5. background 旋转_基于HTML5 Canvas实现工控2D叶轮旋转
  6. 苹果被咬一大口!高通获得45亿美元和解金 下一个目标是华为?
  7. 线程范围内的线程共享(多线程)
  8. C语言书籍推荐从入门到进阶再到封神全套(2021年整理)
  9. php智能电视如何安装直播软件,海信 LED 55EC520UA 怎么安装第三方软件看直播?教你安装方法...
  10. 人体姿态识别方案详解
  11. js prototype 原型对象
  12. 无线路由器当无线交换机后,如何进入路由器配置界面
  13. 密码学原语如何应用?解析单向哈希的妙用|第9论
  14. WidgetOne手机应用开发平台已正式上线
  15. 春季必买明星款流行春装
  16. 01-初探MQ-MQ的三大使用场景:应用解耦、异步提速、削峰填谷
  17. linux系统的7种banding方式
  18. Android 获取通讯录数据
  19. 怎么找生物信息论文的数据,PubMed太有用了!
  20. Android应用代码混淆

热门文章

  1. Matlab使用心得
  2. Thread was being aborted.(调试或执行较长时间的程序时发生的错误)
  3. Oracle数据导入导出imp/exp命令 10g以上expdp/impdp命令
  4. 架构师之路(2)---详解面向过程
  5. window上安装fasttext
  6. 【知识图谱系列】基于生成式的知识图谱预训练模型
  7. 天池NLP文本分类比赛如何轻松轻松获得Top K的秘诀!
  8. 一文总结熵,交叉熵与交叉熵损失
  9. 加速BERT:从架构优化、模型压缩到模型蒸馏最新进展详解
  10. 【福利派送】高质量AI书籍又免费派送啦