• 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',
                ]
            }
  • 相关阅读:
    layout_weight使用
    Android sdk manager 下载速度慢的问题
    详谈OC(object-c)深浅复制/拷贝-什么情况下用retain和copy
    object-c(oc)内存管理机制详解
    xmpp实现的即时通讯聊天(二)
    xmpp实现的即时通讯聊天(一)
    iOS开发消息推送原理
    指定的转换无效。
    Oracle11g +Win 64+PLSQL9.0
    数据库连接字符串
  • 原文地址:https://www.cnblogs.com/654321cc/p/8511395.html
Copyright © 2020-2023  润新知