Django-rest_framework

DRF里有十个组件:

  1. 认证
  2. 权限
  3. 节流
  4. 版本
  5. 解析器
  6. 序列化
  7. 分页
  8. 路由
  9. 视图
  10. 渲染器

Django的请求生命周期

  1. 请求进来–>wsgi -->中间件–>视图
  2. wsgi是一个协议,web服务网关接口 web服务器和web应用之间做一个协议
  3. wsgiref 实现了wsgi协议的一个模块.模块的本质:一个socket服务端.(性能低)
  4. Flask 使用 werkzeug 实现 wsgi协议,模块的本质:一个socket服务端
  5. Django 部署时使用 uwsgi
from wsgiref.simple_server import make_server
#environ请求的相关信息,start_response返回的相关信息
def RunServer(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]

if __name__ == '__main__':
    httpd = make_server('', 8000, RunServer)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()
Django : FBV --> function base view 基于函数的视图
def users(request):
    user_list=['格式','二哥']
    return HttpResponse(json.dumps(user_list))
Django: CBV -->class base view 基于类的视图 基于反射实现根据请求方式不同,执行不同的方法
路由
urlpatterns = [
    url(r'^students/',views.StudentView.as_view())
]
from django.views import View
http_method_names =['get','post','put','patch','delete','head','options','trace']
class StudentView(View):
    #def dispatch(self,request,*args,**kwargs):
        #GET请求会运行dispatch函数
        #return HttpResponse('dispatch')
        #func = getattr(self,request.method.lower())
        #ret = func(request,*args,**kwargs)
        #return ret
        #ret=super(StudentView,self).dispathc(request,*args,**kwargs)
        #return ret
    def get(self,request,*args,**kwargs)
    	return HttpResponse('GET')
    def post(self,request,*args,**kwargs):
        return HttpResponse('POST')
    def put(self,request,*args,**kwargs):
        return HttpResponse('PUT')
    def delete(self,request,*args,**kwargs):
        return HttpResponse('DELETE')
CBV内部实现原理:
  1. 路由:url --> view方法 ->dispatch方法(反射执行其他:GET/POST/DELETE/PUT)
面向对象
  • 封装,继承,多态

  • 封装 体现在两大方面:

  1. 类可以对同一类的方法做一次封装;
  2. 将数据封装到对象中
  3. rest_framework 中当请求进来时 DRF把 Django的 reqeust 进行封装,自定义的分页

补充:鸭子模型 : 以下是维基百科中对鸭子类型得论述:

​ 在程序设计中,**鸭子类型(英语:duck typing)是动态类型的一种风格。**在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:

​ “当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

  • 在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。

  • 在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。

  • 在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。

  • 鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的(在运行之前的)类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。

  • 代码展示

class WC:
    def send():
        pass
class Em:
    def send():
        pass
class Mn:
    def send():
        pass
def fun(arg):
    arg.send()
    
xx = Mn()
fun(xx)#只要xx有send方法,就不管xx对象是什么
Django的中间件:
  1. process_request
  2. process_response
  3. process_view
  4. process_exception
  5. process_render_template
中间件应用场景(适用于对所有的请求做批量操作):
  1. 基于角色的权限

  2. 用户登录认证

  3. django的csrf 在process_view中 检查视图是否被 @csrf_token装饰,去请求体或cookie中或取token

  4. session

  5. 黑名单

  6. 日志记录

    from django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt #这个装饰器的作用是免除下面的函数进行csrf_token认证
    def users(reqeust):
        user_list=['sg','gb']
        return HttpResponse(json.dumps(user_list))
    
    from django.views.decorators.csrf import csrf_protect
    
    @csrf_protect #该函数需要csrf的认证
    def users(reqeust):
        user_list=['sg','gb']
        return HttpResponse(json.dumps(user_list))
    

    在视图类里使用csrf_token装饰器

    from django.utils.decorators import method_decorator
    
    class StudentView(View):
        @method_decorator(csrf_exempt)
        def dispatch(self,request,*args,**kwargs):
            return super(StudnetView,self).dispatch(request,*args,**kwargs)
        
        def get(self,request,*args,**kwargs)
        	return HttpResponse('GET')
    
    from django.utils.decorators import method_decorator
    
    @method_decorator(csrf_exempt,name='dispatch')
    class StudentView(View):
        def get(self,request,*args,**kwargs)
        	return HttpResponse('GET')
    
    • 本质,基于反射来实现
    • 流程:路由 ,view,dispatch(反射)
    • 取消csrf(认证) ---->装饰器要加到dispatch方法上,需要method_decorator
restful 规范 十个规范
  • API与用户的通信协议,总是使用HTTPs协议

  • 域名

  • 版本

  • 路径,是网络上任何东西都是资源,均使用名词表示(可复数)

  • method

  • 过滤,通过在url上传参的形式传递搜索条件

  • 状态码

  • 错误处理,状态码是4xx时,应返回错误信息,error当做键

  • 返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范

  • GET /collection:返回资源对象的列表(数组)
    GET /collection/resource:返回单个资源对象
    POST /collection:返回新生成的资源对象
    PUT /collection/resource:返回完整的资源对象
    PATCH /collection/resource:返回完整的资源对象
    DELETE /collection/resource:返回一个空文档
    
  • Hypermedia API,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么

  1. 根据method的不同做不同的操作

    urlpatterns=[
        url(r'^order/',views.order)
    ]
    def order(request):
        if request.method == 'GET':
            return HttpResponse('获取订单')
        elif request.method == 'POST':
            return HttpResponse('创建订单')
        elif request.method == 'PUT':
            return HttpResponse('更新订单')
        elif request.method =='DELETE':
            return HttpResponse('删除订单')
    
    urlpatterns=[
        url(r'^order',views.OrderView.as_view())
    ]
    class OrderView(View):
        if request.method == 'GET':
            return HttpResponse('获取订单')
        elif request.method == 'POST':
            return HttpResponse('创建订单')
        elif request.method == 'PUT':
            return HttpResponse('更新订单')
        elif request.method =='DELETE':
            return HttpResponse('删除订单')
    

    rest_framework生命周期:

    请求–>wsgi–>中间件–>路由匹配–>CBV的类–>as_view() view函数执行 dispatch request封装 走 认证/权限/节流,经过反射找到请求对应的方法;–>中间件–>wsgi–>用户

    认证:

    局部视图使用

    from rest_framework exceptions
    from rest_framework.views import APIView
    from rest_framework.authentication import BaseAuthentication
    
    class MyAuthentication(BaseAuthentication):
        def authenticate(self, request):
            token = request._request.GET.get('token')
            if not token:
                raise exception.AuthenticationFailed('用户认证失败')
            return ('用户名', None)
        def authenticate_header(self, val):
            pass
        
    class DogView(APIView):
        authentication_classes = [MyAuthenticaton,]
        def get(self, request, *args, **kwargs):
            #self.dispatch CBV 通过反射实现
          	#print(request) #rest_framework 加工之后的request
            #print(reqeust.user) ==> authenticate函数里的 用户名
            data={
                'code':85296,
                'msg':'gsadg'
            }
            return HttpResponse(json.dumps(data))
        
    
    • 认证流程原理:

      请求到视图类的 self.dispatch --> self.initial(reqeust) 对reqeust进行封装–>self.get_authenticator -->self.authenticator_classes -->默认去配置文件读 authenticator_classes 函数里有就用函数中的, ‘’‘authentication_classes = [MyAuthenticaton,]’’’ 没有就去全局找 ‘’‘authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES’’’–>Request.user.self._authenticate()(循环authentication_classes = [MyAuthenticaton,] )–>执行认证类的 authenticator.authenticate(self)(情况1.如果authenticate方法抛出异常, self._not_authenticated()执行;2.如果没有抛出异常 :a. user_auth_tuple里有值return ('用户名', None)把值赋值给 self.user,self.auth ,b. user_auth_tuple没有返回值 执行 self._not_authenticated() -->user=匿名用户, auth=None) -->get/post函数

把认证写在配置文件中
#表示全局认证
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES":['api.util.auth.认证类名',]#认证类的路径,需要新建一个文件夹和文件,认证类写到文件中
	#匿名用户
    #"UNAUTHENTICATED_USER":lambda:"匿名用户",
    "UNAUTHENTICATED_USER":None,#如果是匿名,reqeust.user=None
    "UNAUTHENTICATED_TOKEN":None,#request.auth = None
}
#如果有的函数不需要认证则在函数中添加
authentcation_classes = []


认证流程:

dispatch -->封装request -->获取定义的认证类(全局/局部),通过列表生成时创建对象

​ -->initial–>perform_authentication -->request.user(内部循环…)

权限:

#源码位置:
self.dispatch -->self.initial 
self.check_permissions(request)

#权限类
from rest_framework.permissions import BasePermission
class MyPermission(BasePermission):
    message='必须是SVIP才能访问'
    def has_permission(self, request, view):
        if request.user.user_type != 3:
            return False
        return True
class MyPermission1(BasePermission):
    def has_permission(self, request, view):
        if request.user.user_type == 3:
            return False
        return True
    #在进行普通权限认证时下面这个函数不会被调用,只有在 GenericAPIView.get_object调用时 会调用 check_object_permission之后调用has_object_permission
    def has_object_permission(self, request, view, obj):
        pass
class OrderView(APIView):
    '''订单相关业务(只有SVIP用户有权限)'''
    authentication_classes = [Authtication,]
    permission_classes = [MyPermission,]
    def get(self, request, *args, **kwargs):
        #权限判断
        # if request.user.user_type !=3:
        #     return HttpResponse('无权访问')
        ret = {'code':1000,'error':None,'data':None}
        try:
            ret['data'] = ORDER_DICT#一个数据字典
        except Exception as e:
            pass
        return JsonResponse(ret)

class UserinfoView(APIView):
    '''用户中心(普通用户和VIP用户看)'''
    authentication_classes = [Authtication,]
    permission_classes = [MyPermission1,]
    def get(self, request, *args, **kwargs):
        return JsonResponse('用户信息')
全局设置
REST_FRAMEWORK={
    'DEFAULT_PERMISSION_CLASSES':['api.util.permission.MyPermission','api.util.permission.MyPermission1']
}

使用
- 类,继承BasePermission 实现 has_permission 方法
- 返回值 True 有权访问 False无权访问

节流(控制接口访问频率):

#源码位置:
self.dispatch -->self.initial 
self.check_throttles(request)

#基本方法实现节流
from rest_framework.throttling import BaseThrottle
import time
VISIT_RECORO={}  #放到缓存里
class VisitThrottld(BaseThrottle):

    def __init__(self):
        self.history = None
        
    def allow_request(self,request,view):
        '''判断频率是否已经达到最大限度,60s内只能访问3次'''
        #获取代理
        #xff = request.META.get('HTTP_X_FORWARDED_FOR')
        #获取用户IP
        #remote_addr = request._request.META.get('REMOTE_ADDR')
        #remote_addr = request.META.get('REMOTE_ADDR')
        remote_addr = self.get_ident(request)
        print(remote_addr)
        ctime = time.time()
        if remote_addr not in VISIT_RECORO:
            VISIT_RECORO[remote_addr] = [ctime]
            return True

        history = VISIT_RECORO.get(remote_addr, [])
        self.history = history

        while history and history[-1] < ctime - 10:
            history.pop()

        if len(history) < 3:
            history.insert(0,ctime)
            return True

        # return True  #可以继续访问
        #return False #表示访问频率太高,进行限制
    def wait(self):
        '''还需要等多少秒才能访问'''
        ctime = time.time()

        return 10 - (ctime - self.history[-1])

class AuthView(APIView):
    '''用户登录'''
    #authentication_classes = [Authtication,]
    throttle_classes = [VisitThrottld,]
获取IP:

remote_addr = request._request.META.get(‘REMOTE_ADDR’)

​ remote_addr = request.META.get(‘REMOTE_ADDR’)

django 内置的缓存 cache = default_cache cache.get(key,[]) 获取内容 cache.set(key, [], 多少时间间隔)

内置控制频率的类:
from rest_framework.throttling import SimpleRateThrottle
#对匿名用户的控制
class VisitThrottld(SimpleRateThrottle):
	scope = 'visit' #以后当key用
    def get_cache_key(self, request, view):
        return self.get_ident(request)
    
    
#对登录用户的控制    
class UserThrottld(SimpleRateThrottle):
    scope = 'User'
    def get_cache_key(self, request, view):
        return request.user.username
    
    
#当把节流放到配置中,未登录类,进行匿名节流控制  
class AuthView(APIView):
    '''用户登录'''
    #authentication_classes = [Authtication,]
    throttle_classes = [VisitThrottld,]
    def post(self, reqeust, *args, **kwargs):
        # self.dispatch
        ret = {'code':1000,'error':None}
        try:
            user=reqeust._request.POST.get('username')
            pwd = reqeust._request.POST.get('password')
            obj = UserInfo.objects.filter(username=user,password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['error'] = '用户名密码错误'
            #为用户创建token
            token = md5(user)
            # print(token)
            #存在就更新,不存在就创建
            UserToken.objects.update_or_create(user=obj,defaults={'token':token})
            ret['token'] = token
        except Exception as e:
            ret['code'] = 1002
            ret['error'] = '请求异常'

        return JsonResponse(ret)
    

配置文件

		...
"DEFAULT_THROTTLE_CLASSES":['节流类的路径.UserThrottld'],
"DEFAULT_THROTTLE_RATES":{
    "visit":'3/m' #一分钟访问3次
    "User":'10/m' #登录用户一分钟访问10次
}

版本:

  1. 在GET方法中传参:
#源码位置:
self.dispatch -->self.initial 
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme

#路由:
url(r'^users/$', views.UserView.as_view(),name='user')#该路径传值是通过GET传值
from rest_framework.versioning import BaseVsersion

#自定义获取版本信息
class ParamVersion(BaseVsersion):
    def determine_version(self, request,*args,**kwargs):
        version = request.query_params.get('version')
        return version
    
class UserView(APIView):

    # versioning_class = ParamVersion

    def get(self,request,*args,**kwargs):
        #获取版本信息两种方法
        # version=request._request.GET.get('version')
        # print(version)
        #
        # version=request.query_params.get('version')
        # print(version)
        #写class 1.获取版本
        print(request.version)
#流程 : 请求进来-->封装request-->处理版本-->认证权限-->截留
        #获取处理版本的对象
        #2.获取版本对象
        print(request.versioning_scheme)#反向生成url
        #反向生成url需要添加version request=request request里就有version
        #3.反向生成url
        url = request.versioning_scheme.reverse(viewname='user',request=request)
        print(url)

        return HttpResponse("用户列表")
#源码:
class QueryParameterVersioning(BaseVersioning):
    """
    GET /something/?version=0.1 HTTP/1.1
    Host: example.com
    Accept: application/json
    """
    invalid_version_message = _('Invalid version in query parameter.')

    def determine_version(self, request, *args, **kwargs):
        version = request.query_params.get(self.version_param, self.default_version)
        if not self.is_allowed_version(version):
            raise exceptions.NotFound(self.invalid_version_message)
        return version
    
#这里有三个配置 :
#self.version_param, 传参时 urlwww.sss.com/api/?key = xx 中的key值设置
#self.default_version,默认的版本
#self.is_allowed_version,允许的版本

settins.py文件中:

REST_FRAMEWORK = {
	"DEFAULT_VERSION":'V1',
    "ALLOWED_VERSIONS":['V1','V2'],
    "VERSION_PARAM":'version',
}

DRF内置的类:

from rest_framework.versioning import QueryParameterVersioning

class UserView(APIView):
    versioning_class = QueryParameterVersioning
    
    def get(self,request,*args,**kwargs):
    
        print(request.version)

        return HttpResponse("用户列表")

路径二(在URL中传参):

url(r'^(?P<version>[v1|v2]+)/users/$', views.UserView.as_view())#在URL中传信息
from rest_framework.versioning import URLPathVersioning

class UserView(APIView):
    #versioning_class = URLPathVersioning
    
    def get(self,request,*args,**kwargs):
    
        print(request.version)

        return HttpResponse("用户列表")

settings.py中:

REST_FRAMEWORK = {
    "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",#不用对每一个类进行设置
	"DEFAULT_VERSION":'V1',
    "ALLOWED_VERSIONS":['V1','V2'],
    "VERSION_PARAM":'version',
}

反向生成URL:

#路由:
url(r'^(?P<version>[v1|v2]+)/users/$', views.UserView.as_view(),
        name='user')
from django.url import reverse

class UserView(APIView):
    #versioning_class = URLPathVersioning
    
    def get(self,request,*args,**kwargs):
    
        print(request.version)
        #rest_framework反向生成url
        url = reqeust.versioning_scheme.reverse(viewname='user',request = request)
		#url1 = reverse(viewname='user',kwargs = {'version'}:1)#django反向生成url
        return HttpResponse("用户列表")

解析器:

  1. Django解析器:

    • django: reqeust.POST/request.body
    1. 如果请求头中的 Content_Type : application/x-www-form-urlencoded;request.POST中才有值(去request.body中解析数据)

    2. 数据格式要求: name = ‘xxx’&age=18&gender=‘男’

      如: form表单提交:

      <form method...>
          input...
          
      </form>
      

      ajax提交:

      $.ajax({
      	url:...,
      	type:POST,
      	data:{name:xxx,age=18} #内部转化 name=xxx&age=18&gender=男
      })
      
      $.ajax({
      	url:...,
      	type:POST,
      	headers:{"Content-Type":"application/json"}
      	data:{name:xxx,age=18} #内部转化 name=xxx&age=18&gender=男
      })
      #request.body中有值,request.POST中没有值
      
      $.ajax({
      	url:...,
      	type:POST,
      	headers:{"Content-Type":"application/json"}
      	data:JSON.stringfy({name:xxx,age=18}) #内部转化 {name:xxx,age=18}
      })
      #reqeust.body中有值,request.POST中没有值
      #json.loads(request.body)获取值
      

2.rest_framework解析器:

from rest_framework.parsers import JSONParser

class ParserView(APIView):
    #允许用户发送JSON格式数据
    parser_classes = [JSONParser,]
    def post(self, request, *args, **kwargs):
        print(reqeust.data) #获取解析后的结果
        return HttpResponse('提交成功')

解析器一般配置在全局:

REST_FRAMEWORK = {
	"DEFAULT_PARSER_CLASSES":['rest_framework.parsers.JSONParser','rest_framework.parsers.FormParser']#传递的数据是json或form表单数据
}

MultiPartParser,FileUploadParser这两个类可以实现文件上传

#路由:
urlpatterns = [
    url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
]


from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FileUploadParser
#在需要上传文件的类里添加
class TestView(APIView):
    parser_classes = [FileUploadParser, ]

    def post(self, request, filename, *args, **kwargs):
        print(filename)
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

序列化:

功能:

  1. 对请求数据的验证
  2. 对query_set进行序列化

models.py

class UserInfo(models.Model):
    username = models.CharField(max_length=32,unique=True)
    password = models.CharField(max_length=64)
    roles = models.ManyToManyField(to='Role')

class Role(models.Model):
    title = models.CharField(max_length=32)

views.py

from rest_framework import serializers
from .models import Role
class RolesSerializer(serializers.Serializer):
    id=serializers.IntegerField()
    title=serializers.CharField()

class RolesView(APIView):

    def get(self,request,*args,**kwargs):
        #方式一:
        # roles=Role.objects.all().values('id','title')
        # roles=list(roles)
        # return HttpResponse(json.dumps(roles,ensure_ascii=False))

        #方式二:
        roles=Role.objects.all()
        ser=RolesSerializer(instance=roles,many=True)
        ret=json.dumps(ser.data,ensure_ascii=False)

        #roles = Role.objects.first()获取一个对象
        #ser = RolesSerializer(instance=roles, many=False)

        #ser.data已经是转化完成的结果
        ret = json.dumps(ret.data, ensure_ascii=False)
        return HttpResponse(ret)

分页:

  1. 看第n页,每页显示n条数据
  2. 在某个位置,向后查看n条数据
  3. 加密分页,看上一页和下一页
url(r'^(?P<version>[v1|v2]+)/pager1/$', views.PagerView.as_view(),
        name='pg'),
from rest_framework.views import APIView
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,MyCursorPagination

#自定制分页类
class MyPageNumberPagination(PageNumberPagination):
    page_size = 2 #一页显示2个
    page_size_query_param = 'size' #可以在一页显示自定制个数据
    max_page_size = 5 #最大显示数

    page_query_param = 'page'
    
#在位置向后查看
class MyLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 2 #一页默认显示2个数据
    limit_query_param = 'limit'#向后取n条

    offset_query_param = 'offset' #从第n为开始取 www.xxx

    max_limit = 5  #向后最多取5个数据


class MyCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'
    page_size = 2
    ordering = 'id' #按ID排序
    page_size_query_param = None
    max_page_size = 5

class PagerSerialiser(serializers.ModelSerializer):
    class Meta:
        model = Role
        fields = '__all__'
        
class PagerView(APIView):
    def get(self,request,*args,**kwargs):
        #获取所有数据
        roles = Role.objects.all()
        #1.创建分页对象  page参数
        #pp = MyPageNumberPagination
        #2.limit 分页
        # pp = LimitOffsetPagination()
        #pp = MyLimitOffsetPagination()
        #3.cursor 分页
        pp = MyCursorPagination()
        #在数据库中获取分页的数据
        pager_roles=pp.paginate_queryset(queryset=roles,request=request,view=self)
        # ret = json.dumps(ser.data,ensure_ascii=False)
        #对数据进行序列化
        ser = PagerSerialiser(instance=pager_roles, many=True)
        #return Response(ser.data)
        
        #帮助我们返回response,帮助完成上一页下一页链接生成展示
        return pp.get_paginated_response(ser.data)

视图:

第一个类 APIView

class ParserView(APIView):
    def post(self, request, *args, **kwargs):
        print(reqeust.data) #获取解析后的结果
        return HttpResponse('提交成功')

第二个类:GenericAPIView

url(r'^(?P<version>[v1|v2]+)/vie/$', views.VieView.as_view(),
        name='vi'),
from rest_framework.generics import GenericAPIView
#GenericAPIView 继承了APIView
class VieView(GenericAPIView):#继承了APIView 帮我们完成了分页,等一些功能
    queryset = Role.objects.all()
    serializer_class = PagerSerialiser
    pagination_class = PageNumberPagination
    def get(self,request,*args,**kwargs):
        #获取数据
        roles = self.get_queryset()#Role.objects.all()
        #进行分页
        pager_roles = self.paginate_queryset(roles)
        #序列化
        ser= self.get_serializer(instance=pager_roles,many=True)
        
    	reutrn Response(ser.data)

第三个类: GenericViewSet

url(r'^(?P<version>[v1|v2]+)/vie/$', views.VieView.as_view({'get':'list','post':'poo'}),
        name='vi'),
from rest_framework.viewsets import GenericViewSet

#GenericViewSet(ViewSetMixin, generice.GenericAPIView) 继承了两个类
#ViewSetMixin 把路由中 as_view()重写了
class VieView(GenericViewSet):
    queryset = Role.objects.all()
    serializer_class = PagerSerialiser
    pagination_class = PageNumberPagination
    def list(self,request,*args,**kwargs):
        #获取数据
        roles = self.get_queryset()#Role.objects.all()
        #进行分页
        pager_roles = self.paginate_queryset(roles)
        #序列化
        ser= self.get_serializer(instance=pager_roles,many=True)
        
    	reutrn Response(ser.data)
    def poo(self,request,*args,**kwargs):
    	reutrn Response('...') 

第四个类:ModelViewSet

#路由
url(r'^(?P<version>[v1|v2]+)/vie/$', views.VieView.as_view({'get':'list','post':'poo'}),
        name='vi'),
url(r'^(?P<version>[v1|v2]+)/vie1/(?<pk>\d+)/$', views.Vie1View.as_view({'get':'list','post':'poo'}),
        name='v1'),
url(r'^(?P<version>[v1|v2]+)/vie1/(?<pk>\d+)/$', views.Vie1View.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':''}),
        name='v1'),
from rest_framework.viewsets import GenericViewSet,ModelViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,

#ListModelMixin以经把list功能写好了  get请求
#CreateModelMixin把添加功能写好了	post请求
#UpdateModelMixin把更新全部功能写好了   put请求    更新个别功能 patch请求
#DestroyModelMixin把删除功能写好了  delete请求
#RetrieveModelMixin 获取个别信息功能 get 请求
#ModelViewSet把上面所有的类继承了,如果继承ModelViewSet直接实现增删改查功能
class VieView(ListModelMixin,GenericViewSet): 
    queryset = Role.objects.all()
    serializer_class = PagerSerialiser
    pagination_class = PageNumberPagination
    
class Vie1View(ModelViewSet): 
    queryset = Role.objects.all()
    serializer_class = PagerSerialiser
    pagination_class = PageNumberPagination

总结:

  • 需要增删改查 -->ModelViewSet
  • 只需要增删 --> CreateModelMixin,DestroyModelMixin,GenericViewSet
  • 需要复杂的逻辑 GenericViewSet 或 APIView

路由

  • url(r'^(?P<version>[v1|v2]+)/vie/$', views.VieView.as_view(),
            name='vi'),
    
  • url(r'^(?P<version>[v1|v2]+)/vie1/(?<pk>\d+)/$',views.Vie1View.as_view({'get':'list','post':'poo'}),name='v1')
    
  • #http://127.0.0.1:8000/api/v1/?format=json
    url(r'^(?P<version>[v1|v2]+)/v1/(?<pk>\d+)/$',views.V1View.as_view({'get':'list','post':'poo'}),name='v1')
    
    #http://127.0.0.1:8000/api/v1.json
    url(r'^(?P<version>[v1|v2]+)/v1\.(?P<format>\w+)$',views.V1View.as_view({'get':'list','post':'poo'}),name='v1')
    
  • #当用ModelViewSet类时,路由可以自动生成
    from rest_framework import routers
    
    router= routers.DefaultRouter()
    router.register(r'xxx',views.V1View)#视图类
    
    urlpatterns = [
        url(r'^(?P<version>[v1|v2]+)/',include(router.urls)),
    ]
    

渲染:

#路由
url(r'^(?P<version>[v1|v2]+)/test/$', views.TestView.as_view()),
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer,AdminRenderer,HTMLFormRenderer

class TestView(APIView):
    #渲染器配置
    # renderer_classes =[JSONRenderer,BrowsableAPIRenderer]

    def get(self, request, *args, **kwargs):
        roles = Role.objects.all()

        pg=MyCursorPagination()
        pager_roles = pg.paginate_queryset(isinstance=roles,request=request, view=self)
        ser = PagerSerialiser(instance=pager_roles, many=True)

        return Response(ser.data)
#如果使用 AdminRenderer
#路由
#http://127.0.0.1:8000/api/test.admin
url(r'^(?P<version>[v1|v2]+)/test\.(?P<format>\w+)$', views.TestView.as_view()),

以上就是我对 rest_framework 组件的理解和部分使用.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值