zoukankan      html  css  js  c++  java
  • DAY102

    一、手动编写配置文件

    # 默认配置
    # conf-->global_setting.py
    DEBUG = None
    
    TIME_ZONE = 'America/Chicago'
    
    USE_TZ = False
    
    
    # 用户配置
    # usersetting-->setting.py
    DEBUG = True
    
    TIME_ZONE = 'Asia/Shanghai'
    
    USE_TZ = False
    
    ABC='123'
    
    
    # conf-->__init__.py
    from conf import global_setting
    import os
    import importlib
    
    
    class MySetting():
        # dir:返回模块的属性列表
        def __init__(self):
    
            settings_module = os.environ.get('USER_SETTING')
            # 通过环境变量,获得用户配置的文件路径(字符串)
            # settings_module = 'usersetting.setting'
            
            # 循环获得默认配置的值
            for setting in dir(global_setting):
                if setting.isupper():
                    setattr(self, setting, getattr(global_setting, setting))
    		
            # 使用importlib.import_module()获得用户配置的路径
            mod = importlib.import_module(settings_module)
    		
            # 循环获得用户配置的值,会覆盖默认配置
            for setting in dir(mod):
                if setting.isupper():
                    setattr(self, setting, getattr(mod, setting))
    
    
    setting = MySetting()
    
    # 运行文件
    import os
    
    os.environ.setdefault('USER_SETTING', 'usersetting.setting')
    
    from conf import setting
    print(setting.DEBUG)
    
    

    二、分页器

    1.普通分页

    基本使用

    # 普通分页
    from rest_framework.pagination import PageNumberPagination
    
    class Books(APIView):
        def get(self, request):
            books = models.Book.objects.all()
            # 生成一个PageNumberPagination对象
            page = PageNumberPagination()
            # 第一个参数:要分页的数据,第二个参数request对象,第三个参数,当前视图对象
            # 在数据库中获取分页的数据
            page_list = page.paginate_queryset(books, request, self)
            ret = BooksSerializer(instance=page_list, many=True)
            print(ret.data)
            return Response(ret.data)
        
            # 这个也是返回Response对象,但是比基本的多了上一页,下一页,和总数据条数(了解即可)
            # return page.get_paginated_response(ret.data)
    
    # setting.py
    # 配置每页显示数
    REST_FRAMEWORK = {
        # 每页显示两条
        'PAGE_SIZE': 2
    }
    

    配置属性

    # 方法一:自定义分页类继承PageNumberPagination
    
    class MyPageNumberPagination(PageNumberPagination):
        # 每页显示的数据数,默认去setting里找
        page_size = 3
        
        # 配置GET里接收的key:value形式的key值,可以指定当前页
        # http://127.0.0.1:8000/books/?p=2
        # 默认为page
        page_query_param = 'p'
        
        # 可以通过URL的方式指定每页显示的数据数
        # http://127.0.0.1:8000/books/?page=2&size=1
        # 默认为size
        page_size_query_param='s'
        
        # 每页最多显示数据数
        max_page_size = 4
    
    
    class Books(APIView):
        def get(self, request):
            books = models.Book.objects.all()
            # 生成一个自定义的对象
            page = MyPageNumberPagination()
            page_list = page.paginate_queryset(books, request, self)
            ret = BooksSerializer(instance=page_list, many=True)
            print(ret.data)
            return Response(ret.data)
    
    # 方式二:视图里设置属性
    class Books(APIView):
        def get(self, request):
            books = models.Book.objects.all()
            page = PageNumberPagination()
            page.page_size = 3
            page.page_query_param = 'page'
            page.page_size_query_param = 'size'
            page.max_page_size = 4
            page_list = page.paginate_queryset(books, request, self)
            ret = BooksSerializer(instance=page_list, many=True)
            print(ret.data)
            return Response(ret.data)
    

    2.偏移分页

    基本使用

    # 偏移分页
    from rest_framework.pagination import LimitOffsetPagination
    
    class Books(APIView):
        def get(self, request):
            books = models.Book.objects.all()
            # 生成一个LimitOffsetPagination对象
            page = LimitOffsetPagination()
            # 第一个参数:要分页的数据,第二个参数request对象,第三个参数,当前视图对象
            # 在数据库中获取分页的数据
            page_list = page.paginate_queryset(books, request, self)
            ret = BooksSerializer(instance=page_list, many=True)
            print(ret.data)
            return Response(ret.data)
        
            # 这个也是返回Response对象,但是比基本的多了上一页,下一页,和总数据条数(了解即可)
            # return page.get_paginated_response(ret.data)
    
    # setting.py
    # 配置每页显示数
    REST_FRAMEWORK = {
        # 每页显示两条
        'default_limit':2
    }
    

    配置属性

    # 配置属性的两种方法与普通分页一样
    # 每页显示的条数
    default_limit = api_settings.PAGE_SIZE
    
    # 标杆值
    # 配置GET里接收的key:value形式的key值,可以指定标杆值
    # 一般和limit_query_param一起使用
    # 默认为offset,可以自定义
    offset_query_param = 'offset'
    
    # 可以通过URL的方式指定每页显示的数据数
    # http://127.0.0.1:8000/books/?offset=4&limit=3
    # 从第四条数据(不包括)开始取三条数据
    # 如果写了limit=3,会覆盖default_limit的数据数
    # 默认为limit,可以自定义
    limit_query_param = 'limit'
    
    # 每页显示最大的条数
    # 如果写了limit的值>max_limit的值,以max_limit为准
    max_limit = None
    

    3.加密分页

    基本使用

    # 加密分页
    from rest_framework.pagination import CursorPagination
    
    class Books(APIView):
        def get(self, request):
            books = models.Book.objects.all()
            # 生成一个PageNumberPagination对象
            page = CursorPagination()
            # 先把数据按照ordering排序,再从数据库取出来
            page.ordering = 'id'
            
            page_list = page.paginate_queryset(books, request, self)
            ret = BooksSerializer(instance=page_list, many=True)
            return Response(ret.data)
            # page.get_paginated_response()会返回链接和总的数据数
            # return page.get_paginated_response(ret.data)
    
    # setting.py
    # 配置每页显示数
    REST_FRAMEWORK = {
        # 每页显示两条
        'PAGE_SIZE': 2,
    }
    

    配置属性

    # 配置属性的两种方法与普通分页一样'
    # 每页显示的条数
    page_size = api_settings.PAGE_SIZE
    
    # 在URL显示加密后的页码
    # http://127.0.0.1:8000/books/?cursor=cD0y
    # 默认为cursor,可以自定义
    cursor_query_param = 'cursor
    
    # 数据按照ordering排序,默认是'-created'
    ordering = '-created'
    
    # 每页最多显示数据数
    max_page_size = 4
    

    三、版本控制

    基于restful规范,应当由版本之分,rest-framework给我们提供了一个

    from rest_framework.versioning import QueryParameterVersioning,AcceptHeaderVersioning,NamespaceVersioning,URLPathVersioning
    
    # 基于url的get传参方式:
    #  QueryParameterVersioning------>如:/users?version=v1
    
    # 基于url的正则方式:
    #  URLPathVersioning------>/v1/users/
    
    # 基于 accept 请求头方式:
    #  AcceptHeaderVersioning------>Accept: application/json; version=1.0
    
    # 基于主机名方法:
    #  HostNameVersioning------>v1.example.com
    
    # 基于django路由系统的namespace:
    #  NamespaceVersioning------>example.com/v1/users/
    
    

    基本使用

    # 路由
    url(r'^(?P<version>[v1|v2|v3]+)/books/', views.Books.as_view()),
    
    from rest_framework.versioning import URLPathVersioning
    
    
    class Books(APIView):
        # 局部使用
        versioning_class = URLPathVersioning
    
        def get(self, request,*args,**kwargs):
            books = models.Book.objects.all()
            # 获得版本号
            print(request.version)
            # URLPathVersioning对象
    		print(request.versioning_scheme)
            
            ret = BooksSerializer(books, many=True)
            return Response(ret.data)
        
    #全局使用
    REST_FRAMEWORK = {
        'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
        'DEFAULT_VERSION': 'v1',            # 默认版本(从request对象里取不到,显示的默认值)
        'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
        'VERSION_PARAM': 'version'          # URL中获取值的key
    }
    

    反向解析

    # url
    url(r'^(?P<version>[v1|v2|v3]+)/books/', views.Books.as_view(),name='test'),
    
    
    # 反向生成URL
    # 第一个参数是路由名,第二个是request
    reverse_url = request.versioning_scheme.reverse('test', request=request)
    print(reverse_url)
    # http://127.0.0.1:8000/v1/books/
    

    源码解析

    # 第一步
    # dispatch()
    def dispatch(self, request, *args, **kwargs):
        
    	........
        # 由此进入下一步
        self.initial(request, *args, **kwargs)
    	
        ........
        
    
    # 第二步
    # initial()
    def initial(self, request, *args, **kwargs):
    
        ........
        # 把determine_version方法的返回值解压赋值给version和scheme
        # 也就是version = 版本号
        # scheme = 版本类对象
        version, scheme = self.determine_version(request, *args, **kwargs)
        # 再把version和scheme分别赋值给request
        request.version, request.versioning_scheme = version, scheme
        
        ........
        
    
    # 第三步
    # self.determine_version()
    def determine_version(self, request, *args, **kwargs):
        
        # 如果versioning_class is None,返回空元组
        if self.versioning_class is None:
            return (None, None)
        
        # 如果有,就加上()执行
        # 从视图里找,有:versioning_class = URLPathVersioning
        # scheme = URLPathVersioning()
        # 也就是说scheme是URLPathVersioning实例化后的对象
        scheme = self.versioning_class()
        
        # 返回元组(scheme.determine_version(request, *args, **kwargs),scheme)
        # scheme.determine_version(),是在URLPathVersioning里的方法
        return (scheme.determine_version(request, *args, **kwargs), scheme)
    
    # 第四步
    # URLPathVersioning ---> determine_version
    def determine_version(self, request, *args, **kwargs):
        # version_param和default_version都会从setting里找
        # version_param='version'
        # default_version='v1'
        # 假设url: http://127.0.0.1:8000/v2/books/
        # 从参数里找url传进来的version,也就是v2,没有就默认值self.default_version
        version = kwargs.get(self.version_param, self.default_version)
        
        # is_allowed_version,从下往上找,都没有,在父类BaseVersioning里
        # 也就是说,如果返回True,就直接把接收到的version返回,false则抛异常
        if not self.is_allowed_version(version):
            raise exceptions.NotFound(self.invalid_version_message)
        return version
    
    
    # BaseVersioning ---> is_allowed_version()
    def is_allowed_version(self, version):
        # 如果视图里没有,会从setting里找,还没有,就去默认里找,默认里是None,就返回True
        # 也就是说,如果setting里写了但为空,或者没写,就返回True
        if not self.allowed_versions:
            return True
        
        # 只要version为空并且version不在allowed_versions范围内
        # 或者version不等于默认值default_version并且version不在allowed_versions范围内
        # 就会返回false
        return ((version is not None and version == self.default_version) or(version in self.allowed_versions))
    
  • 相关阅读:
    Android-----图片处理工具
    Android-----使用zxing实现二维码扫描
    Android-----调用系统相机拍照并把照片展示在图库中
    Android-----使用SoapObject获取服务器数据
    Android-----实现给图片添加字体
    Android-----WebView加载HTML界面布局并进行数据交互
    Android-----File(文件各种操作)
    Android-----创建SQLite数据库
    Android-----spinner组件使用(实现下单)
    SpringBoot学习日记1:HelloWorld
  • 原文地址:https://www.cnblogs.com/xvchengqi/p/10139251.html
Copyright © 2011-2022 走看看