restframework

一   认证

  核心代码

class OrderView(APIView):
    authentication_classes = [Authentication,]
    def get(self,request,*args,**kwargs):
          pass
class Authentication(object):
    def authenticate(self,request):

        token = request._request.GET.get('token')
        token_obj = models.UserToken.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed('用户认证失败!')
        return (token_obj.user,token_obj)
    def authenticate_header(self,request):
        pass

  源码流程:

 

 

  1 dispatch

  2 封装request

  3 initial方法

  4 perform_authentication方法

  5 6  request.user
  7 self._authenticate方法 返回值有三种情况,空,报错,(request.user,request.auth)

  8 循环 

 

1. 认证
a. 问题1:有些API需要用户登录成功之后,才能访问;有些无需登录就能访问。
b. 基本使用认证组件
解决:
a. 创建两张表
b. 用户登录(返回token并保存到数据库)
c. 认证流程原理
- 见图示

d. 再看一遍源码
1. 局部视图使用&全局使用
2. 匿名是request.user = None

e. 内置认证类
1. 认证类,必须继承:from rest_framework.authentication import BaseAuthentication
2. 其他认证类:BasicAuthentication

 

梳理:
1. 使用
- 创建类:继承BaseAuthentication; 实现:authenticate方法
- 返回值:
- None,我不管了,下一认证来执行。
- raise exceptions.AuthenticationFailed('用户认证失败') # from rest_framework import exceptions
- (元素1,元素2) # 元素1赋值给request.user; 元素2赋值给request.auth

- 局部使用
from rest_framework.authentication import BaseAuthentication,BasicAuthentication
class UserInfoView(APIView):
"""
订单相关业务
"""
authentication_classes = [BasicAuthentication,]
def get(self,request,*args,**kwargs):
print(request.user)
return HttpResponse('用户信息')
- 全局使用:
REST_FRAMEWORK = {
# 全局使用的认证类
"DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication', ],
# "UNAUTHENTICATED_USER":lambda :"匿名用户"
"UNAUTHENTICATED_USER":None, # 匿名,request.user = None
"UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None
}
2. 源码流程
- dispatch
- 封装request
- 获取定义的认证类(全局/局部),通过列表生成时创建对象。
- initial
- perform_authentication
request.user(内部循环....)

 

二 权限

问题:不用视图不用权限可以访问

基本使用:

class MyPermission(object):

def has_permission(self,request,view):
if request.user.user_type != 3:
return False
return True


class OrderView(APIView):
"""
订单相关业务(只有SVIP用户有权限)
"""
permission_classes = [MyPermission,]

def get(self,request,*args,**kwargs):
# request.user
# request.auth
self.dispatch
ret = {'code':1000,'msg':None,'data':None}
try:
ret['data'] = ORDER_DICT
except Exception as e:
pass
return JsonResponse(ret)

源码流程:
- ...

梳理:
1. 使用
- 类,必须继承:BasePermission,必须实现:has_permission方法
from rest_framework.permissions import BasePermission

class SVIPPermission(BasePermission):
message = "必须是SVIP才能访问"
def has_permission(self,request,view):
if request.user.user_type != 3:
return False
return True
- 返回值:
- True, 有权访问
- False,无权访问
- 局部
class UserInfoView(APIView):
"""
订单相关业务(普通用户、VIP)
"""
permission_classes = [MyPermission1, ]

def get(self,request,*args,**kwargs):
return HttpResponse('用户信息')

- 全局
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES":['api.utils.permission.SVIPPermission']
}

2. 源码流程

三 节流

问题:控制访问频率
import time
VISIT_RECORD = {}

class VisitThrottle(object):
"""60s内只能访问3次"""

def __init__(self):
self.history = None

def allow_request(self,request,view):
# 1. 获取用户IP
remote_addr = request.META.get('REMOTE_ADDR')
ctime = time.time()
if remote_addr not in VISIT_RECORD:
VISIT_RECORD[remote_addr] = [ctime,]
return True
history = VISIT_RECORD.get(remote_addr)
self.history = history

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

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

# return True # 表示可以继续访问
# return False # 表示访问频率太高,被限制

def wait(self):
"""
还需要等多少秒才能访问
:return:
"""
ctime = time.time()
return 60 - (ctime - self.history[-1])

class AuthView(APIView):
"""
用于用户登录认证
"""
authentication_classes = []
permission_classes = []
throttle_classes = [VisitThrottle,]

def post(self,request,*args,**kwargs):


ret = {'code':1000,'msg':None}
try:
user = request._request.POST.get('username')
pwd = request._request.POST.get('password')
obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
if not obj:
ret['code'] = 1001
ret['msg'] = "用户名或密码错误"
# 为登录用户创建token
token = md5(user)
# 存在就更新,不存在就创建
models.UserToken.objects.update_or_create(user=obj,defaults={'token':token})
ret['token'] = token
except Exception as e:
ret['code'] = 1002
ret['msg'] = '请求异常'

return JsonResponse(ret)

源码流程:
...

内置控制频率类:
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
class VisitThrottle(SimpleRateThrottle):
scope = "Luffy"

def get_cache_key(self, request, view):
return self.get_ident(request)


class UserThrottle(SimpleRateThrottle):
scope = "LuffyUser"

def get_cache_key(self, request, view):
return request.user.username


REST_FRAMEWORK = {
# 全局使用的认证类
"DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication', ],
# "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication', ],
# "UNAUTHENTICATED_USER":lambda :"匿名用户"
"UNAUTHENTICATED_USER":None, # 匿名,request.user = None
"UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None
"DEFAULT_PERMISSION_CLASSES":['api.utils.permission.SVIPPermission'],
"DEFAULT_THROTTLE_CLASSES":["api.utils.throttle.UserThrottle"],
"DEFAULT_THROTTLE_RATES":{
"Luffy":'3/m',
"LuffyUser":'10/m',
}
}

 

四 版本

  1 127.0.0.1:8000/api/users/?version=xx 的样式,在url中通过get传参

    1)自定义

class MyVersion(object):
    def determine_version(self,request,*args,**kwargs):
        return request._request.GET.get('version')

class UserView(APIView):
    versioning_class = MyVersion
    def get(self,request,*args,**kwargs):
        print(request.version)
        return HttpResponse('用户列表')

    2)内置类 QueryParameterVersioning

from rest_framework.views import APIView
from rest_framework.versioning import QueryParameterVersioning
# class MyVersion(object):
#     def determine_version(self,request,*args,**kwargs):
#         return request._request.GET.get('version')

class UserView(APIView):
    versioning_class = QueryParameterVersioning
    def get(self,request,*args,**kwargs):
        print(request.version)
        return HttpResponse('用户列表')

  全局设置 

REST_FRAMEWORK = {
                "DEFAULT_VERSION":'v1',
                "ALLOWED_VERSIONS":['v1','v2'],
                "VERSION_PARAM":'version',
            }

  2  127.0.0.1:8000/api/v1/users/ 在url中传参,推荐

  

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/users/$',views.UserView.as_view()),
]
from rest_framework.versioning import URLPathVersioning
class UserView(APIView):
    def get(self,request,*args,**kwargs):
        print(request.version)
        return HttpResponse('用户列表')
REST_FRAMEWORK = {
                "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
                "DEFAULT_VERSION":'v1',
                "ALLOWED_VERSIONS":['v1','v2'],
                "VERSION_PARAM":'version',
            }

 

        总结:
            使用:
                配置文件:
                    REST_FRAMEWORK = {
                        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
                        "DEFAULT_VERSION":'v1',
                        "ALLOWED_VERSIONS":['v1','v2'],
                        "VERSION_PARAM":'version',
                    }
                路由系统:
                                        
                    urlpatterns = [
                        # url(r'^admin/', admin.site.urls),
                        url(r'^api/', include('api.urls')),
                    ]

                    urlpatterns = [
                        # url(r'^admin/', admin.site.urls),
                        url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view(),name='uuu'),
                    ]
                            
                
                视图:
                    
                    class UsersView(APIView):

                    def get(self,request,*args,**kwargs):
                
                        # 1. 获取版本
                        print(request.version)
                        
                        # 2. 获取处理版本的对象
                        print(request.versioning_scheme)

                        # 3. 反向生成URL(rest framework)
                        u1 = request.versioning_scheme.reverse(viewname='uuu',request=request)
                        print(u1)

                        # 4. 反向生成URL
                        u2 = reverse(viewname='uuu',kwargs={'version':2})
                        print(u2)

                        return HttpResponse('用户列表')

 五 解析器   对请求体数据进行解析

  铺垫

  request.POST中有值的两个条件

    1 请求头要求:Content-Type: application/x-www-form-urlencoded

    2 数据体要求:name=alex&age=18&gender=男

  如

    a:form表单提交,默认符合

    b:ajax提交

$.ajax({
                        url:...
                        type:POST,
                        data:{name:alex,age=18} # 内部转化 name=alex&age=18&gender=男
                    })
                    
                    情况一:
                        $.ajax({
                            url:...
                            type:POST,
                            headers:{'Content-Type':"application/json"}
                            data:{name:alex,age=18} # 内部转化 name=alex&age=18&gender=男
                        })
                        # body有值;POST无
                    情况二:
                        $.ajax({
                            url:...
                            type:POST,
                            headers:{'Content-Type':"application/json"}
                            data:JSON.stringfy({name:alex,age=18}) # {name:alex,age:18...}
                        })
                        # body有值;POST无
                        # json.loads(request.body)

 

总结:
            使用:    
                配置:
                    REST_FRAMEWORK = {
                        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
                        "DEFAULT_VERSION":'v1',
                        "ALLOWED_VERSIONS":['v1','v2'],
                        "VERSION_PARAM":'version',
                        
                        "DEFAULT_PARSER_CLASSES":['rest_framework.parsers.JSONParser','rest_framework.parsers.FormParser']
                    }
                                
                使用:
                    class ParserView(APIView):
                        # parser_classes = [JSONParser,FormParser,]
                        """
                        JSONParser:表示只能解析content-type:application/json头
                        JSONParser:表示只能解析content-type:application/x-www-form-urlencoded头
                        """

                        def post(self,request,*args,**kwargs):
                            """
                            允许用户发送JSON格式数据
                                a. content-type: application/json
                                b. {'name':'alex',age:18}
                            :param request:
                            :param args:
                            :param kwargs:
                            :return:
                            """
                            """
                            1. 获取用户请求
                            2. 获取用户请求体
                            3. 根据用户请求头 和 parser_classes = [JSONParser,FormParser,] 中支持的请求头进行比较
                            4. JSONParser对象去请求体
                            5. request.data
                            """
                            print(request.data)


                            return HttpResponse('ParserView')
                            
        
            源码流程 & 本质:
                a. 本质 
                    请求头 :...
                    状态码: ...
                    请求方法:...
                b. 源码流程 
                    - dispatch: request封装 
                    - request.data 

 

六 序列化

  序列化的两个作用: 

    1) 序列化

              2 )请求数据校验

  作用 1

from rest_framework import serializers
class RoleSerialize(serializers.Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField()

class RoleView(APIView):
    # 方式一  比较low的方法
    # def get(self,request,*args,**kwargs):
    #     roles = models.Role.objects.all().values('id','title')
    #     roles = list(roles)
    #     return HttpResponse(json.dumps(roles))
    # 方式二
    def get(self,request,*args,**kwargs):
        roles = models.Role.objects.all()
        ser = RoleSerialize(instance=roles,many=True)
        print(ser.data)
        return HttpResponse(json.dumps(ser.data))

 

  进阶1 关于choices

Model:
class
UserInfo(models.Model): user_type_choices = ( (1,'NORM'), (2,'VIP'), (3,'SVIP'), ) user_type = models.IntegerField(choices=user_type_choices,default=1) username = models.CharField(max_length=32) password = models.CharField(max_length=64) usergroup = models.ForeignKey(to='UserGroup') roles = models.ManyToManyField('Role')
CBV:
class
UserinfoSerialize(serializers.Serializer): user_type = serializers.CharField(source='get_user_type_display') # user_type字典 前面加get_,后面加_display username = serializers.CharField() class UserInfoView(APIView): def get(self,request,*args,**kwargs): users = models.UserInfo.objects.all() ser = UserinfoSerialize(instance=users,many=True) return HttpResponse(json.dumps(ser.data))

  进阶二,关于外键

  model:

class UserInfo(models.Model):
    user_type_choices = (
        (1,'NORM'),
        (2,'VIP'),
        (3,'SVIP'),
    )
    user_type = models.IntegerField(choices=user_type_choices,default=1)
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    usergroup = models.ForeignKey(to='UserGroup')
    roles = models.ManyToManyField('Role')
class UserGroup(models.Model):
    title = models.CharField(max_length=32)

  视图:

class UserinfoSerialize(serializers.Serializer):
    user_type = serializers.CharField(source='get_user_type_display')
    username = serializers.CharField()
    group = serializers.CharField(source='usergroup.title') #通过.调用
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserinfoSerialize(instance=users,many=True)
        return HttpResponse(json.dumps(ser.data))

  进阶三 关于多对多

  model

class UserInfo(models.Model):
    user_type_choices = (
        (1,'NORM'),
        (2,'VIP'),
        (3,'SVIP'),
    )
    user_type = models.IntegerField(choices=user_type_choices,default=1)
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    usergroup = models.ForeignKey(to='UserGroup')
    roles = models.ManyToManyField('Role')
class Role(models.Model):
    title = models.CharField(max_length=32)

  视图:

class UserinfoSerialize(serializers.Serializer):
    user_type = serializers.CharField(source='get_user_type_display')
    username = serializers.CharField()
    group = serializers.CharField(source='usergroup.title')
    roles = serializers.SerializerMethodField() #自定义显示
    def get_roles(self,row): #row 代表当前行的对象,
        roles_list = row.roles.all()
        ret = []
        for item in roles_list:
            ret.append({'id':item.id,'title':item.title})
        return ret  #返回啥,页面显示啥
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserinfoSerialize(instance=users,many=True)
        return HttpResponse(json.dumps(ser.data))

  进阶四。每个字段都写,很难受,简单的做法

class UserinfoSerialize(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = '__all__'
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserinfoSerialize(instance=users,many=True)
        return HttpResponse(json.dumps(ser.data))

  但是,显示也简单了

[{"id": 1, "user_type": 1, "username": "loda", "password": "123", "usergroup": 2, "roles": [1]}, {"id": 2, "user_type": 1, "username": "s4", "password": "123", "usergroup": 2, "roles": [2, 3]}, {"id": 3, "user_type": 1, "username": "bulldog", "password": "123", "usergroup": 2, "roles": [3]}, {"id": 4, "user_type": 2, "username": "miracle", "password": "123", "usergroup": 1, "roles": [1, 2]}, {"id": 5, "user_type": 2, "username": "krokky", "password": "123", "usergroup": 1, "roles": [1, 3]}, {"id": 6, "user_type": 2, "username": "mind_contrlo", "password": "123", "usergroup": 1, "roles": [3]}]

  进阶五 最终版本 混合使用

class UserinfoSerialize(serializers.ModelSerializer):
    roles = serializers.SerializerMethodField()  # 自定义显示
    def get_roles(self,row): #row 代表当前行的对象,
        roles_list = row.roles.all()
        ret = []
        for item in roles_list:
            ret.append({'id':item.id,'title':item.title})
        return ret  #返回啥,页面显示啥
    class Meta:
        model = models.UserInfo
        # fields = '__all__'
        fields = ['username','password','roles']
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserinfoSerialize(instance=users,many=True)
        return HttpResponse(json.dumps(ser.data))

  显示:

[{"username": "loda", "password": "123", "roles": [{"id": 1, "title": "carry"}]}, {"username": "s4", "password": "123", "roles": [{"id": 2, "title": "mid"}, {"id": 3, "title": "support"}]}, {"username": "bulldog", "password": "123", "roles": [{"id": 3, "title": "support"}]}, {"username": "miracle", "password": "123", "roles": [{"id": 1, "title": "carry"}, {"id": 2, "title": "mid"}]}, {"username": "krokky", "password": "123", "roles": [{"id": 1, "title": "carry"}, {"id": 3, "title": "support"}]}, {"username": "mind_contrlo", "password": "123", "roles": [{"id": 3, "title": "support"}]}]

   进阶六: 自动序列化连表 depth

  视图:

class UserinfoSerialize(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = '__all__'
        depth = 1
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserinfoSerialize(instance=users,many=True)
        return HttpResponse(json.dumps(ser.data))

  输出: 完美!

[{"id": 1, "user_type": 1, "username": "loda", "password": "123", "usergroup": {"id": 2, "title": "allience"}, "roles": [{"id": 1, "title": "carry"}]}, {"id": 2, "user_type": 1, "username": "s4", "password": "123", "usergroup": {"id": 2, "title": "allience"}, "roles": [{"id": 2, "title": "mid"}, {"id": 3, "title": "support"}]}, {"id": 3, "user_type": 1, "username": "bulldog", "password": "123", "usergroup": {"id": 2, "title": "allience"}, "roles": [{"id": 3, "title": "support"}]}, {"id": 4, "user_type": 2, "username": "miracle", "password": "123", "usergroup": {"id": 1, "title": "liquid"}, "roles": [{"id": 1, "title": "carry"}, {"id": 2, "title": "mid"}]}, {"id": 5, "user_type": 2, "username": "krokky", "password": "123", "usergroup": {"id": 1, "title": "liquid"}, "roles": [{"id": 1, "title": "carry"}, {"id": 3, "title": "support"}]}, {"id": 6, "user_type": 2, "username": "mind_contrlo", "password": "123", "usergroup": {"id": 1, "title": "liquid"}, "roles": [{"id": 3, "title": "support"}]}]

 

总结:

1. 写类
                    class RolesSerializer(serializers.Serializer):
                        id = serializers.IntegerField()
                        title = serializers.CharField()
            
                    class UserInfoSerializer(serializers.ModelSerializer):
                        class Meta:
                            model = models.UserInfo
                            # fields = "__all__"
                            fields = ['id','username','password',]
            
                2. 字段 
                    a. title = serializers.CharField(source="xxx.xxx.xx.xx")
                    b. title = serializers.SerializerMethodField()
                       class UserInfoSerializer(serializers.ModelSerializer):
                            rls = serializers.SerializerMethodField()  # 自定义显示

                            class Meta:
                                model = models.UserInfo
                                fields = ['id','username','password','rls',]
                            
                            # 自定义方法
                            def get_rls(self, row):
                                role_obj_list = row.roles.all()

                                ret = []
                                for item in role_obj_list:
                                    ret.append({'id':item.id,'title':item.title})
                                return ret
                    c. 自定义类
                        
                3. 自动序列化连表
                    class UserInfoSerializer(serializers.ModelSerializer):
                    class Meta:
                        model = models.UserInfo
                        # fields = "__all__"
                        fields = ['id','username','password','group','roles']
                        depth = 1 # 0 ~ 10
            
                4. 生成链接
                    class UserInfoSerializer(serializers.ModelSerializer):
                        group = serializers.HyperlinkedIdentityField(view_name='gp',lookup_field='group_id',lookup_url_kwarg='xxx')
                        class Meta:
                            model = models.UserInfo
                            # fields = "__all__"
                            fields = ['id','username','password','group','roles']
                            depth = 0 # 0 ~ 10

                    class UserInfoView(APIView):
                        def get(self,request,*args,**kwargs):

                            users = models.UserInfo.objects.all()

                            ser = UserInfoSerializer(instance=users,many=True,context={'request': request})
                            ret = json.dumps(ser.data, ensure_ascii=False)
                            return HttpResponse(ret)

 

  作用2  请求数据校验

class UserGroupSerialize(serializers.Serializer):
    title = serializers.CharField(error_messages={'required':'标题不能为空'})

class UserGroupView(APIView):
    def post(self,request,*args,**kwargs):
        ser = UserGroupSerialize(data=request.data)
        if ser.is_valid():
            print(ser.validated_data['title'])
        else:
            print(ser.errors)
        return HttpResponse('xxx')

   钩子函数

    def validate_字段名(self,value):

      if True:

        return value

      else:

        raise ..

    

class RoleSerialize(serializers.Serializer):
    title = serializers.CharField(error_messages={'required':'不能为空!'})
    def validate_title(self,value):
        print(value)
        if 1:
            raise exceptions.ValidationError('shabi')
        else:
            return value
class RoleView(APIView):
    # 方式一  比较low的方法
    # def get(self,request,*args,**kwargs):
    #     roles = models.Role.objects.all().values('id','title')
    #     roles = list(roles)
    #     return HttpResponse(json.dumps(roles))
    # 方式二
    def post(self,request,*args,**kwargs):
        roles = models.Role.objects.all()
        # ser = RoleSerialize(instance=roles,many=True)
        ser = RoleSerialize(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)
            print(ser.errors['title'])
        # print(ser.data)
        return HttpResponse('xxx')

 

七  分页

  第一种  看第n页,每页显示n条数据。

  啥都不干的最开始的代码。

  model

class UserInfo(models.Model):
    user_type_choices = (
        (1,'NORM'),
        (2,'VIP'),
        (3,'SVIP'),
    )
    user_type = models.IntegerField(choices=user_type_choices,default=1)
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    usergroup = models.ForeignKey(to='UserGroup')
    roles = models.ManyToManyField('Role')

  视图 :单纯的将序列化后的数据返回。

from rest_framework import serializers
from api import models
class UserinfoSerialize(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = '__all__'
        depth = 1
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserinfoSerialize(instance=users,many=True)
        return HttpResponse(json.dumps(ser.data))

  路由

url(r'^(?P<version>[v1|v2]+)/users/$',views.UserInfoView.as_view()),

  通过postman,显示如下。很难看。

[{"id": 1, "user_type": 1, "username": "loda", "password": "123", "usergroup": {"id": 2, "title": "allience"}, "roles": [{"id": 1, "title": "carry"}]}, {"id": 2, "user_type": 1, "username": "s4", "password": "123", "usergroup": {"id": 2, "title": "allience"}, "roles": [{"id": 2, "title": "mid"}, {"id": 3, "title": "support"}]}, {"id": 3, "user_type": 1, "username": "bulldog", "password": "123", "usergroup": {"id": 2, "title": "allience"}, "roles": [{"id": 3, "title": "support"}]}, {"id": 4, "user_type": 2, "username": "miracle", "password": "123", "usergroup": {"id": 1, "title": "liquid"}, "roles": [{"id": 1, "title": "carry"}, {"id": 2, "title": "mid"}]}, {"id": 5, "user_type": 2, "username": "krokky", "password": "123", "usergroup": {"id": 1, "title": "liquid"}, "roles": [{"id": 1, "title": "carry"}, {"id": 3, "title": "support"}]}, {"id": 6, "user_type": 2, "username": "mind_contrlo", "password": "123", "usergroup": {"id": 1, "title": "liquid"}, "roles": [{"id": 3, "title": "support"}]}, {"id": 7, "user_type": 2, "username": "akke", "password": "123", "usergroup": {"id": 2, "title": "allience"}, "roles": []}, {"id": 8, "user_type": 3, "username": "matubman", "password": "123", "usergroup": {"id": 1, "title": "liquid"}, "roles": []}, {"id": 9, "user_type": 3, "username": "gh", "password": "123", "usergroup": {"id": 1, "title": "liquid"}, "roles": []}, {"id": 10, "user_type": 1, "username": "hao", "password": "123", "usergroup": {"id": 3, "title": "newbee"}, "roles": []}, {"id": 11, "user_type": 2, "username": "mu", "password": "123", "usergroup": {"id": 3, "title": "newbee"}, "roles": []}, {"id": 12, "user_type": 3, "username": "xiao8", "password": "123", "usergroup": {"id": 3, "title": "newbee"}, "roles": []}, {"id": 13, "user_type": 1, "username": "sansheng", "password": "123", "usergroup": {"id": 3, "title": "newbee"}, "roles": []}, {"id": 14, "user_type": 2, "username": "banana", "password": "123", "usergroup": {"id": 3, "title": "newbee"}, "roles": []}]

  运用渲染 进阶1 :

    1 在settings.py 的 installed_apps里 注册rest_framework,

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'api.apps.ApiConfig',
    'rest_framework',
]

    2 导入Response,返回时甚至连都不需要json,都帮你做好了。

from rest_framework.response import Response
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        ser = UserinfoSerialize(instance=users,many=True)
        # return HttpResponse(json.dumps(ser.data))
        return Response(ser.data)

  改完后,页面显示如下。

  

   牛不牛逼!

 

  进阶2 

  使用内置的分页

from api.utils.serializer.userinfo import UserinfoSerialize
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        page = PageNumberPagination() #实例化
        #返回 分页后的对象,即page_users,而不是所有对象,users
        page_users = page.paginate_queryset(queryset=users,request=request,view=self) #queryset=从数据库拿到的queryset类型数据,view=当前视图的对象
        ser = UserinfoSerialize(instance=page_users,many=True)
        # return HttpResponse(json.dumps(ser.data))
        return Response(ser.data)

  内置,可以在url加?page=x,调到某一页。

  

 

  进阶3 基于PageNumberPagination的基础上自定义分页

from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
    page_size = 3
    page_query_param = 'page'
    page_size_query_param = 'size'
    max_page_size = 10
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        page = MyPageNumberPagination() #实例化
        #返回 分页后的对象,即page_users,而不是所有对象,users
        page_users = page.paginate_queryset(queryset=users,request=request,view=self) #queryset=从数据库拿到的queryset类型数据,view=当前视图的对象
        ser = UserinfoSerialize(instance=page_users,many=True)
        # return HttpResponse(json.dumps(ser.data))
        return Response(ser.data)

  可以实现内置分页类,并不能实现的在url后面加size参数的功能。另外,尽管全局设置为page=3,当前引用的自定义类,page=2,也是以引用的自定义的分页类为准。

    

   进阶四 

    返回更为详细的数据

    视图

class MyPageNumberPagination(PageNumberPagination):
    page_size = 3
    page_query_param = 'page'
    page_size_query_param = 'size'
    max_page_size = 10
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        page = MyPageNumberPagination() #实例化
        #返回 分页后的对象,即page_users,而不是所有对象,users
        page_users = page.paginate_queryset(queryset=users,request=request,view=self) #queryset=从数据库拿到的queryset类型数据,view=当前视图的对象
        ser = UserinfoSerialize(instance=page_users,many=True)
        # return HttpResponse(json.dumps(ser.data))
        # return Response(ser.data)
        return page.get_paginated_response(data=ser.data) #!!

  访问成功后显示:

  其中,next,previous,都是超链接。

  

 

  第二种  在第n位置,向后查看n条数据

  LimitOffsetPagination

from rest_framework.pagination import LimitOffsetPagination

class MyPageNumberPagination(LimitOffsetPagination):
    limit_query_param = 'limit'
    offset_query_param = 'offset'
    max_limit = 5
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        page = MyPageNumberPagination() #实例化
        #返回 分页后的对象,即page_users,而不是所有对象,users
        page_users = page.paginate_queryset(queryset=users,request=request,view=self) #queryset=从数据库拿到的queryset类型数据,view=当前视图的对象
        ser = UserinfoSerialize(instance=page_users,many=True)
        # return HttpResponse(json.dumps(ser.data))
        # return Response(ser.data)
        return page.get_paginated_response(data=ser.data)

  样式:

  

  第三种 加密分页 上一页,下一页

class MyPageNumberPagination(CursorPagination):
    cursor_query_param = 'cursor'
    page_size = 4
    # invalid_cursor_message = _('Invalid cursor')
    ordering = 'id'
    page_size_query_param = 'size'
    max_page_size = 10
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objects.all()
        page = MyPageNumberPagination() #实例化
        #返回 分页后的对象,即page_users,而不是所有对象,users
        page_users = page.paginate_queryset(queryset=users,request=request,view=self) #queryset=从数据库拿到的queryset类型数据,view=当前视图的对象
        ser = UserinfoSerialize(instance=page_users,many=True)
        # return HttpResponse(json.dumps(ser.data))
        # return Response(ser.data)
        return page.get_paginated_response(data=ser.data)

  页面显示:

  注意,这一种分页,必须使用page.get_paginated_response。因为在url中cursor='' 是什么你是不知道的,只能点上一页,下一页。

  

 

 

八 视图

  视图的继承关系

  

 

 GenericViewSet 实现了 as_view({'get':'xx'...})

 视图:

from rest_framework.viewsets import ModelViewSet

class UserInfoView(ModelViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserinfoSerialize
    pagination_class = PageNumberPagination

  路由:

url(r'^(?P<version>[v1|v2]+)/users/$',views.UserInfoView.as_view({'post':'create','get':'list'})),
    url(r'^(?P<version>[v1|v2]+)/users/(?P<pk>\d+)/$',views.UserInfoView.as_view({'get':'retrieve','put':'update','patch':'partial_update','delete':'destroy'})),

   总结:

    a. 增删改查 ModelViewSet
    b. 增删 CreateModelMixin,DestroyModelMixin GenericViewSet
    c. 复杂逻辑 GenericViewSet 或 APIView

九 路由 

a.
  url(r'^(?P<version>[v1|v2]+)/parser/$', views.ParserView.as_view()),
b.
  url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view({'get': 'list','post':'create'})),
c.
  # http://127.0.0.1:8000/api/v1/v1/?format=json
  url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view({'get': 'list','post':'create'})),
  # http://127.0.0.1:8000/api/v1/v1.json
  url(r'^(?P<version>[v1|v2]+)/v1\.(?P<format>\w+)$', views.View1View.as_view({'get': 'list','post':'create'})),

  url(r'^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$', views.View1View.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
  url(r'^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)\.(?P<format>\w+)$', views.View1View.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
d.
  from api import views
  from rest_framework import routers

  router = routers.DefaultRouter()
  router.register(r'users', views.UserInfoView)
  router.register(r'roles', views.RolesView)

  urlpatterns = [
  url(r'^(?P<version>[v1|v2]+)/', include(router.urls)),
  ]

 

 

十  渲染

  局部渲染

class TestView(APIView):
            # renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
            def get(self, request, *args, **kwargs):
               ...

  全局渲染

  

REST_FRAMEWORK = {
           "DEFAULT_RENDERER_CLASSES":[
                'rest_framework.renderers.JSONRenderer',
                'rest_framework.renderers.BrowsableAPIRenderer',
            ]
        }

 

posted @ 2018-03-05 21:11  骑者赶路  阅读(558)  评论(0编辑  收藏  举报