zoukankan      html  css  js  c++  java
  • Restful_Framework之插件

    为了方便接下来的学习,我们创建一个新的子应用 four

    python manage.py startapp four
    

    因为接下来的功能中需要使用到登陆功能,所以我们使用django内置admin站点并创建一个管理员.

    python manage.py createsuperuser
    

    创建管理员以后,访问admin站点,先修改站点的语言配置

    settings.py

    访问admin 站点效果:

    1. 认证Authentication

    可以在配置文件中配置全局默认的认证方案

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.SessionAuthentication',  # session认证
            'rest_framework.authentication.BasicAuthentication',   # 基本认证
        )
    }
    

    也可以在每个视图中通过设置authentication_classes属性来设置

    from rest_framework.authentication import SessionAuthentication, BasicAuthentication
    from rest_framework.views import APIView
    
    class ExampleView(APIView):
        # 类属性
        authentication_classes = [SessionAuthentication, BasicAuthentication]
        ...
    

    认证失败会有两种可能的返回值:

    • 401 Unauthorized 未认证
    • 403 Permission Denied 权限被禁止

    2. 权限Permissions

    权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

    • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
    • 在通过get_object()获取具体对象时,会进行模型对象访问权限的判断

    使用

    可以在配置文件中全局设置默认的权限管理类,如

    # 针对整个站点的所有视图进行权限的判断
    # 针对内部系统,往往才会使用到全局的权限判断,针对允许游客访问的页面,可以在视图中进行单独的开放
    # permission_classes = [AllowAny]
    REST_FRAMEWORK = {
        ....
        
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.IsAuthenticated',
        )
    }
    

    如果未指明,则采用如下默认配置

    'DEFAULT_PERMISSION_CLASSES': (
       'rest_framework.permissions.AllowAny',
    )
    

    也可以在具体的视图中通过permission_classes属性来设置,如

    from rest_framework.permissions import IsAuthenticated
    from rest_framework.views import APIView
    
    class ExampleView(APIView):
        permission_classes = (IsAuthenticated,)
        ...
    

    提供的权限

    • AllowAny 允许所有用户
    • IsAuthenticated 仅通过认证的用户
    • IsAdminUser 仅管理员用户
    • IsAuthenticatedOrReadOnly 已经登陆认证的用户可以对数据进行增删改操作,没有登陆认证的只能查看数据。

    举例

    from rest_framework.authentication import SessionAuthentication
    from rest_framework.permissions import IsAuthenticated
    from rest_framework.generics import RetrieveAPIView
    
    class StudentAPIView(RetrieveAPIView):
        queryset = Student.objects.all()
        serializer_class = StudentSerializer
        authentication_classes = [SessionAuthentication]
        permission_classes = [IsAuthenticated]
    

    自定义权限

    如需自定义权限,需继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部

    • .has_permission(self, request, view)

      是否可以访问视图, view表示当前视图对象

    • .has_object_permission(self, request, view, obj)

      是否可以访问数据对象, view表示当前视图, obj为数据对象

    例如:

    在当前子应用下,创建一个权限文件permissions.py中声明自定义权限类:

    from rest_framework.permissions import BasePermission
    
    class IsXiaoMingPermission(BasePermission):
        def has_permission(self, request, view):
            if( request.user.username == "xiaoming" ):
                return True
    
    from .permissions import IsXiaoMingPermission
    class StudentViewSet(ModelViewSet):
        queryset = Student.objects.all()
        serializer_class = StudentSerializer
        permission_classes = [IsXiaoMingPermission]
    

    3. 限流Throttling

    可以对接口访问的频次进行限制,以减轻服务器压力(很小)。

    一般用于付费购买次数,投票等场景使用.

    使用

    可以在配置文件中,使用DEFAULT_THROTTLE_CLASSESDEFAULT_THROTTLE_RATES进行全局配置,

    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_CLASSES': (
            # 针对匿名用户
            'rest_framework.throttling.AnonRateThrottle',
            # 针对登录用户
            'rest_framework.throttling.UserRateThrottle',
            # 使用自定义限流
            'rest_framework.throttling.ScopedRateThrottle'
        ),
        'DEFAULT_THROTTLE_RATES': {
            'anon': '100/day',  # 匿名用户
            'user': '1000/day'  # 登录用户
        }
    }
    

    DEFAULT_THROTTLE_RATES 可以使用 second, minute, hourday来指明周期。

    也可以在具体视图中通过throttle_classes属性来配置,如

    from rest_framework.throttling import UserRateThrottle
    from rest_framework.views import APIView
    
    class ExampleView(APIView):
        throttle_classes = (UserRateThrottle,)
        ...
    

    可选限流类

    1) AnonRateThrottle

    限制所有匿名未认证用户,使用IP区分用户。

    使用DEFAULT_THROTTLE_RATES['anon'] 来设置频次

    2)UserRateThrottle

    限制认证用户,使用User id 来区分。

    使用DEFAULT_THROTTLE_RATES['user'] 来设置频次

    3)ScopedRateThrottle

    限制用户对于每个视图的访问频次,使用ip或user id。

    例如:

    class ContactListView(APIView):
        throttle_scope = 'contacts'
        ...
    
    class ContactDetailView(APIView):
        throttle_scope = 'contacts'
        ...
    
    class UploadView(APIView):
        throttle_scope = 'uploads'
        ...
    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_CLASSES': (
            'rest_framework.throttling.ScopedRateThrottle',
        ),
        'DEFAULT_THROTTLE_RATES': {
            'contacts': '1000/day',
            'uploads': '20/day'
        }
    }
    

    实例

    全局配置中设置访问频率

        'DEFAULT_THROTTLE_RATES': {
            'anon': '3/minute',
            'user': '10/minute'
        }
    
    from rest_framework.authentication import SessionAuthentication
    from rest_framework.permissions import IsAuthenticated
    from rest_framework.generics import RetrieveAPIView
    from rest_framework.throttling import UserRateThrottle
    
    class StudentAPIView(RetrieveAPIView):
        queryset = Student.objects.all()
        serializer_class = StudentSerializer
        authentication_classes = [SessionAuthentication]
        permission_classes = [IsAuthenticated]
        throttle_classes = (UserRateThrottle,)
    

    4. 过滤Filtering

    对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-filter扩展来增强支持。

    pip install django-filter
    

    在配置文件中增加过滤后端的设置:

    INSTALLED_APPS = [
        ...
        'django_filters',  # 需要注册应用,
    ]
    
    REST_FRAMEWORK = {
        ...
        'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
    }
    

    在视图中添加filter_fields属性,指定可以过滤的字段

    class StudentListView(ListAPIView):
        queryset = Student.objects.all()
        serializer_class = StudentSerializer
        filter_fields = ('age', 'sex')
    
    # 127.0.0.1:8000/four/students/?sex=1
    

    5. 排序

    对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。

    使用方法:

    在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。

    前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。

    示例:

    class StudentListView(ListAPIView):
        queryset = Student.objects.all()
        serializer_class = StudentModelSerializer
        filter_backends = [OrderingFilter]
        ordering_fields = ('id', 'age')
    
    # 127.0.0.1:8000/books/?ordering=-age
    # -id 表示针对id字段进行倒序排序
    # id  表示针对id字段进行升序排序
    

    如果需要在过滤以后再次进行排序,则需要两者结合!

    from rest_framework.generics import ListAPIView
    from students.models import Student
    from .serializers import StudentModelSerializer
    from django_filters.rest_framework import DjangoFilterBackend
    class Student3ListView(ListAPIView):
        queryset = Student.objects.all()
        serializer_class = StudentModelSerializer
        filter_fields = ('age', 'sex')
        # 因为局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明,
        # 否则过滤功能会失效
        filter_backends = [OrderingFilter,DjangoFilterBackend]
        ordering_fields = ('id', 'age')
    

    如果排序时,需要针对多个字段进行排序,则可以使用第二排序

    http://127.0.0.1:8000/home/student_list/?ordering=-age,-id
    # 当age的值都一致的时候,使用id针对这些数据进行倒叙
    

    6. 分页Pagination

    REST framework提供了分页的支持。

    我们可以在配置文件中设置全局的分页方式,如:

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 100  # 每页数目
    }
    

    也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas属性来指明。

    class LargeResultsSetPagination(PageNumberPagination):
        # 每页显示的数据条数
        page_size = 1000
        # 调整page_size的参数名
        page_size_query_param = 'page_size'
        # 每页最大显示条数
        max_page_size = 1000
        # 调整页码的参数,默认page
        page_query_param = 'pn'
    class BookDetailView(RetrieveAPIView):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer
        pagination_class = LargeResultsSetPagination
    

    注意:如果在视图内关闭分页功能,只需在视图内设置

    pagination_class = None
    

    可选分页器

    1) PageNumberPagination

    前端访问网址形式:

    GET  http://127.0.0.1:8000/students/?page=4
    

    可以在子类中定义的属性:

    • page_size 每页数目
    • page_query_param 前端发送的页数关键字名,默认为"page"
    • page_size_query_param 前端发送的每页数目关键字名,默认为None
    • max_page_size 前端最多能设置的每页数量
    # 声明分页的配置类
    from rest_framework.pagination import PageNumberPagination
    class StandardPageNumberPagination(PageNumberPagination):
        # 默认每一页显示的数据量
        page_size = 2
        # 允许客户端通过get参数来控制每一页的数据量
        page_size_query_param = "size"
        max_page_size = 10
        # 自定义页码的参数名
        page_query_param = "p"
    
    class StudentAPIView(ListAPIView):
        queryset = Student.objects.all()
        serializer_class = StudentModelSerializer
        pagination_class = StandardPageNumberPagination
    
    # 127.0.0.1/four/students/?p=1&size=5
    

    2)LimitOffsetPagination

    前端访问网址形式:

    GET http://127.0.0.1/four/students/?limit=100&offset=400
    

    可以在子类中定义的属性:

    • default_limit 默认限制,默认值与PAGE_SIZE设置一直
    • limit_query_param limit参数名,默认'limit'
    • offset_query_param offset参数名,默认'offset'
    • max_limit 最大limit限制,默认None
    from rest_framework.pagination import LimitOffsetPagination
    class StandardLimitOffsetPagination(LimitOffsetPagination):
        # 默认每一页查询的数据量,类似上面的page_size
        default_limit = 2
        # 调整每页数据量的参数
        limit_query_param = "size"
        # 偏移量,即从第几条数据开始查找
        offset_query_param = "start"
    
    class StudentAPIView(ListAPIView):
        queryset = Student.objects.all()
        serializer_class = StudentModelSerializer
        # 调用页码分页类
        # pagination_class = StandardPageNumberPagination
        # 调用查询偏移分页类
        pagination_class = StandardLimitOffsetPagination
    

    7. 异常处理 Exceptions

    REST framework提供了异常处理,我们可以自定义异常处理函数。

    from rest_framework.views import exception_handler
    
    def custom_exception_handler(exc, context):
        # exc:错误对象
        # context:上下文,例如哪个试图报的错,参数有什么,请求对象
        # 先调用REST framework默认的异常处理方法获得标准错误响应对象
        response = exception_handler(exc, context)
    
        # 在此处补充自定义的异常处理
        if response is None:
            response.data['status_code'] = response.status_code
    
        return response
    

    在配置文件中声明自定义的异常处理

    REST_FRAMEWORK = {
        'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
    }
    

    如果未声明,会采用默认的方式,如下

    rest_frame/settings.py

    REST_FRAMEWORK = {
        'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
    }
    

    例如:

    补充上处理关于数据库的异常

    from rest_framework.views import exception_handler
    from django.db import DatabaseError
    from rest_framework.response import Response
    from rest_framework import status
    def customer_execptions(exc, context):
        """自定义异常"""
        # 优先调用drf本身的异常处理,它的返回值要么是None,要么是response
        response = exception_handler(exc, context)
    
        if response is None:
            # 判断是否是数据库
            if isinstance(exc, DatabaseError):
                view = context['view']
                print( '[%s]: %s' % (view, exc) )
                response = Response(data={"msg":"服务器内部存储错误!请联系网站客服管理员!"}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
    
        return response
    

    REST framework定义的异常

    • APIException 所有异常的父类
    • ParseError 解析错误
    • AuthenticationFailed 认证失败
    • NotAuthenticated 尚未认证
    • PermissionDenied 权限决绝
    • NotFound 未找到
    • MethodNotAllowed 请求方式不支持
    • NotAcceptable 要获取的数据格式不支持
    • Throttled 超过限流次数
    • ValidationError 校验失败

    也就是说,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。

    8. 自动生成接口文档

    REST framework可以自动帮助我们生成接口文档。

    接口文档以网页的方式呈现。

    自动接口文档能生成的是继承自APIView及其子类的视图。

    8.1. 安装依赖

    REST framewrok生成接口文档需要coreapi库的支持。

    pip install coreapi
    

    在drf的配置增加配置项:

    REST_FRAMEWORK = {
     	
        # 加载文档声明
        'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
    }
    

    8.2. 设置接口文档访问路径

    在总路由中添加接口文档路径。

    文档路由对应的视图配置为rest_framework.documentation.include_docs_urls

    参数title为接口文档网站的标题。

    from rest_framework.documentation import include_docs_urls
    
    urlpatterns = [
        ...
        path('docs/', include_docs_urls(title='站点页面标题'))
    ]
    

    8.3. 文档描述说明的定义位置

    1) 单一方法的视图,可直接使用类视图的文档字符串,如

    class BookListView(generics.ListAPIView):
        """
        返回所有图书信息.
        """
    

    2)包含多个方法的视图,在类视图的文档字符串中,分开方法定义,如

    class BookListCreateView(generics.ListCreateAPIView):
        """
        get:
        返回所有图书信息.
    
        post:
        新建图书.
        """
    

    3)对于视图集ViewSet,仍在类视图的文档字符串中封开定义,但是应使用action名称区分,如

    class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
        """
        list:
        返回图书列表数据
    
        retrieve:
        返回图书详情数据
    
        latest:
        返回最新的图书数据
    
        read:
        修改图书的阅读量
        """
    

    8.4. 访问接口文档网页

    浏览器访问 127.0.0.1:8000/docs/,即可看到自动生成的接口文档。

    两点说明:

    1) 视图集ViewSet中的retrieve名称,在接口文档网站中叫做read

    2)参数的Description需要在模型类或序列化器类的字段中以help_text选项定义,如:

    class Student(models.Model):
        ...
        age = models.IntegerField(default=0, verbose_name='年龄', help_text='年龄')
        ...
    

    class StudentSerializer(serializers.ModelSerializer):
        class Meta:
            model = Student
            fields = "__all__"
            extra_kwargs = {
                'age': {
                    'required': True,
                    'help_text': '年龄'
                }
            }
    

    9. Xadmin

    xadmin是Django的第三方扩展,比使用Django的admin站点更强大也更方便。

    文档:https://xadmin.readthedocs.io/en/latest/index.html

    9.1. 安装

    通过如下命令安装xadmin的最新版

    pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2
    

    在配置文件中注册如下应用

    INSTALLED_APPS = [
        ...
        'xadmin',
        'crispy_forms',
        'reversion',
        ...
    ]
    
    # 修改使用中文界面
    LANGUAGE_CODE = 'zh-Hans'
    
    # 修改时区
    TIME_ZONE = 'Asia/Shanghai'
    

    xadmin有建立自己的数据库模型类,需要进行数据库迁移

    python manage.py makemigrations
    python manage.py migrate
    

    在总路由中添加xadmin的路由信息

    import xadmin
    xadmin.autodiscover()
    
    # version模块自动注册需要版本控制的 Model
    from xadmin.plugins import xversion
    xversion.register_models()
    
    urlpatterns = [
        path(r'xadmin/', xadmin.site.urls),
    ]
    

    如果之前没有创建超级用户,需要创建,如果有了,则可以直接使用之前的。

    python manage.py createsuperuser
    

    9.2. 使用

    • xadmin不再使用Django的admin.py,而是需要编写代码在adminx.py文件中。
    • xadmin的站点管理类不用继承admin.ModelAdmin,而是直接继承object即可。

    例如:在子应用中创建adminx.py文件。

    站点的全局配置

    import xadmin
    from xadmin import views
    
    class BaseSetting(object):
        """xadmin的基本配置"""
        enable_themes = True  # 开启主题切换功能
        use_bootswatch = True
    
    xadmin.site.register(views.BaseAdminView, BaseSetting)
    
    class GlobalSettings(object):
        """xadmin的全局配置"""
        site_title = "怀心抱素"  # 设置站点标题
        site_footer = "怀心抱素"  # 设置站点的页脚
        menu_style = "accordion"  # 设置菜单折叠
    
    xadmin.site.register(views.CommAdminView, GlobalSettings)
    

    站点Model管理

    xadmin可以使用的页面样式控制基本与Django原生的admin一致。

    • list_display 控制列表展示的字段

      list_display = ['id', 'btitle', 'bread', 'bcomment']
      
    • search_fields 控制可以通过搜索框搜索的字段名称,xadmin使用的是模糊查询

      search_fields = ['id','btitle']
      
    • list_filter 可以进行过滤操作的列,对于分类、性别、状态

      list_filter = ['is_delete']
      
    • ordering 默认排序的字段

    • show_detail_fields 在列表页提供快速显示详情信息

    • list_editable 在列表页可以快速直接编辑的字段

    • refresh_times 指定列表页的定时刷新

      refresh_times = [5, 10,30,60]  # 设置允许后端管理人员按多长时间(秒)刷新页面
      
      
    • list_export 控制列表页导出数据的可选格式

      list_export = ('xls', 'xml', 'json')   list_export设置为None来禁用数据导出功能
      list_export_fields = ('id', 'btitle', 'bpub_date')
      
    • show_bookmarks 控制是否显示书签功能

      show_bookmarks = True
      
    • data_charts 控制显示图表的样式

      data_charts = {
              "order_amount": {
                'title': '图书发布日期表', 
                "x-field": "bpub_date", 
                "y-field": ('btitle',),
                "order": ('id',)
              },
          #    支持生成多个不同的图表
          #    "order_amount": {
          #      'title': '图书发布日期表', 
          #      "x-field": "bpub_date", 
          #      "y-field": ('btitle',),
          #      "order": ('id',)
          #    },
          }
      
      • title 控制图标名称
      • x-field 控制x轴字段
      • y-field 控制y轴字段,可以是多个值
      • order 控制默认排序
    • model_icon 控制菜单的图标【图标的设置可以参考bootstrap的图标css名称】

      class BookInfoAdmin(object):
          model_icon = 'fa fa-gift'
      
      xadmin.site.register(models.BookInfo, BookInfodmin)
      
    • readonly_fields 在编辑页面的只读字段

    • exclude 在编辑页面隐藏的字段

  • 相关阅读:
    Creating a generic Web Parts for hosting ASP.NET User Controls
    Speed Up SQL Server Apps 提高SQL Server应用程序的运行效率 (Part 1)
    How to use CreateChildContorls method inherited from System.Web.UI.Control
    How to quickly access Web Part Management Page
    SQL Script tips for MS SQL Server
    How to enable single signon service on the SPS
    A brief summary of UML & Rational Rose – Use Case Diagram, Part II
    Borland Together for Visual Studio.Net V2.0 安装问题
    Speed Up SQL Server Apps 提高SQL Server应用程序的运行效率 (Part 2)
    体验ReSharper V1.0 for VS.Net 2003 Part I
  • 原文地址:https://www.cnblogs.com/maqian/p/12778916.html
Copyright © 2011-2022 走看看