drf-7

认证组件

# 以后,有的接口需要登录后才能访问,有的接口,不登录就能访问
  -登录认证的限制
  
# 写一个登录接口,返回token,以后只要带着token过来,就是登录了,不带,就没有登录


# 查询所有不需要登录就能访问
# 查询单个,需要登录才能访问

认证组件使用步骤

# 1 写一个认证类,继承BaseAuthentication
# 2 重写authenticate方法,在该方法在中实现登录认证:token在哪带的?如果认证它是登录了
# 3 如果认证成功,放回两个值【返回None或两个值】
# 4 认证不通过,抛异常AuthenticationFailed
# 5 局部使用和全局使用
-局部:只在某个视图类使用【当前视图类管理的所有接口】
			class BookDetailView(ViewSetMixin,RetrieveAPIView):
  				authentication_classes = [LoginAuth]
 -全局:全局所有接口都生效(登录接口不要)
REST_FRAMEWORK = {
 'DEFAULT_AUTHENTICATION_CLASSES':['app01.authenticate.LoginAuth']
}

-局部禁用:
	class BookDetailView(ViewSetMixin, RetrieveAPIView):
            authentication_classes = [] 

新建authenticate.py文件

img

全局方式导入:

img

可以在drf的settings.py中看到

img

代码

###视图
# 查询所有
class BookView(ViewSetMixin, ListAPIView):
  queryset = Book.objects.all()
  serializer_class = BookSerializer
  
 
# 查询单个
class BookDetailView(ViewSetMixin,RetrieveAPIView):
		queryset = Book.objects.all()
    serializer_class = BookSerializer
    #  authentication_classes = [LoginAuth]  # 需要写一个认证类,需要咱们写
    
 # 认证类代码
class LoginAuth(BaseAuthentication):
  def authenticate(self, request):
    # 在这里实现认证,如果是登录的,继续往后走返回两个值,如果不是抛异常
    # 请求中是否携带token,判断是否登录,放在地址栏中
     token = request.query_params.get('token', None)
        if token:  # 前端传入token了,去表中查,如果能查到,登录了,返回两个值[固定的:当前登录用户,token]
            user_token = UserToken.objects.filter(token=token).first()
            if user_token:
                return user_token.user, token
            else:
                # 没有登录抛异常
                raise AuthenticationFailed('token认证失败')
        else:
            raise AuthenticationFailed('token没传')

  
##### 路由代码
router.register('books', views.BookView, 'books')
router.register('books', views.BookDetailView, 'books')

注意:

不要在配置文件中乱导入不使用的东西,否者会报错。

因为,Django的运行是先从配置文件加载的,而导入其他的,文件都没有加载到就直接导入了就会报错。

权限组件

# 即使登录成功了, 有些接口,还是不能访问,因为没有权限

# 登录后,有的接口有权限访问,有的没有权限访问

# 查询单个和查询所有,都要登录才能访问--->全局认证
-查询单个需要超级管理员才能访问
-查询所有,所有登录用户都能访问

# 权限是一个字段,在User表中, 加入user_type字段

权限的使用

# 1 写一个权限类,继承BasePermission
# 2 重写has_permission方法,在该方法在中实现权限认证,在这方法中,request.user就是当前登录用户
# 3 如果有权限,返回Ture
# 4 没有权限,返回False,定制返回的中文:self.message='中文'
# 5 局部使用和全局使用
-局部:只在某个视图类中使用【当前视图类管理的所有接口】
  class BookDetailView(ViewSetMixin,RetrieveAPIView):
  		permission_classes = [CommonPermission]
 -全局:全局所有接口都生效
  		 REST_FRAMEWORK = {
            'DEFAULT_PERMISSION_CLASSES': [
                'app01.permissions.CommonPermission',
            ],

        }
    
    -局部禁用:
    	 class BookDetailView(ViewSetMixin, RetrieveAPIView):
            permission_classes = [] 

当登入的用户的user_type(权限)为1时就是超级管理员就能够访问单条数据

img

频率组件

# 控制某个接口访问频率(次数)
# 查询所有接口,同一个ip一分钟只能访问5个

使用步骤

# 1 写一个频率类 继承SimpleRateThrottle
# 2 重写get_cache_key方法,放回什么,就以什么做限制---->ip,用户id做限制
# 3 配置一个类属性:scope = 'book_5_m'
# 4 在配置文件中配置
  'DEFAULT_THROTTLE_RATES': {
        'book_5_m': '5/m',
    },
# 5 局部使用和全局使用
	-局部:只在某个视图类中使用【当前视图类管理的所有接口】
        class BookDetailView(ViewSetMixin, RetrieveAPIView):
    		throttle_classes = [CommonThrottle]
    -全局:全局所有接口都生效
          REST_FRAMEWORK = {
             'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CommonThrottle'],

        }
    
    -局部禁用:
    	 class BookDetailView(ViewSetMixin, RetrieveAPIView):
            throttle_classes = [] 

分用户ID和IP做限制

img

request.META

img

# request.META
	一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器。
	REMOTE_ADDR —— 客户端的IP 地址
  REMOTE_HOST —— 客户端的主机名
  REMOTE_USER —— 服务器认证后的用户
  更多:https://www.liuqingzheng.top/python/Django%E6%A1%86%E6%9E%B6/6-%E8%A7%86%E5%9B%BE%E5%B1%82/

别忘记配类属性:scope = 'book_5_m'

img

在settings.py源码中

img

得在自己的settings文件中配置,一分钟只能访问5次。有h 1小时多少次

img

过滤排序

5个接口中,只有一个接口需要有过滤和排序,查询所有接口

继承APIView写 (伪代码)

class BookView(APIView):
  def get(self, request):
    search = request.query_params.get('search')
    books = Book.objects.filter(name=self.name)

内置过滤类的使用【继承GenericAPIView】

class BookView(ViewSetMixin,ListAPIView):
  queryset = Book.objects.all()
  serializer_class = BookSerializer
  # SearchFilter内置的,固定用法,模糊匹配
  # 就有过滤功能了,指定按哪个字段过滤
  filter_backends =【SearchFilter】
   # search_fields = ['name']  # 可以按名字模糊匹配
    search_fields = ['name','price']  # 可以按名字模糊匹配或价格模糊匹配
    
 # 可以使用的搜索方式
	http://127.0.0.1:8000/api/v1/books/?search=红  # name或price中只要有红就会搜出来
            
            
# 继承APIView如何写,完全自己写,麻烦,但是清晰     

img

在地址栏中必须以search搜索的模糊查询,查找search_fields中写的字段中包含有搜索的就会查找出来,search_fields中可以写多个字段,

img

使用第三方django-filter实现过滤

安装:Django-filter
from django_fliter.rest_framework import djangoFilterBackend
class BookView(ViewSetMixin, ListAPIView):
  queryset = Book.objects.all()
  serializer_class = BookSerializer
  permission_classes = []
  authentication_classes = []
  throttle_classes = []
  filter_backends = ['name', 'price']  # 支持完整匹配 name=西游记&price=110
  
# 支持的查询方式
http://127.0.0.1:8000/api/v1/books/?price=939
http://127.0.0.1:8000/api/v1/books/?price=939&name=红楼梦

注意跟内置的不一样了:

img

以你在filterset_filelds中写的字段搜索的完整匹配

img

自己定制过滤类实现过滤

# 查询图书价格大于100的所有图书
http://127.0.0.1:8000/api/v1/books/?price_gt=100
    
# 第一步:定义一个过滤类。继承BaseFilterBackend,重写filter——queryset方法

class CommonFilter(BaseFilterBackend):
  def filter_queryset(self, request,view):
    # 在里面是实现过滤,返回qs对象,就是过滤后的数据
    price_gt = requset.query_params.get('price_gt',None)
    if price_gt:
      qs = quesryset.filter(price__get=int(price_get))
      return qs
    else:
      return queryset
# 第二步:配置在视图类上
class BookView(ViewSetMixin, ListAPIView):
  quesryset = Book.objects.all()
  serilizer_class = Bookserializer
  
  filter_backends = [CommonFilter]  # 可以定制多个,从左往右,依次执行

注意这里要CharField是不支持__gt大于的查询比较

img

可以自己指定字段过滤,通过在定义的过滤类里反射

img

img

排序的使用

# 内置的就够了
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [OrderingFilter]  
    ordering_fields = ['price']
    
 # 支持的查询方法:
    http://127.0.0.1:8000/api/v1/books/?ordering=price
    http://127.0.0.1:8000/api/v1/books/?ordering=-price
   http://127.0.0.1:8000/api/v1/books/?ordering=-id,price

img

分页

分页,只有查询所有接口,才有分页

# derf内置分了三个分页器对应三种分页方式

# 内置的分页类不能直接使用,需要继承,定制一些参数后才能使用

源码中GenericAPIView ---> generic中

img

img

为啥不在是一个列表了呢,因为你分页不可能会出现多个分页方式了。

img

分页的使用,自定义一个分页列(三种)

方式一:网页端分页

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination

class CommonpageNumberPagination(PageNumberPagination):
  page_size = 2  # 每页显示2条
  page_query_param = 'page'  # page=10 查询第10页的数据,每页显示2条
  page_size_query_param = 'size'  # page=10&size=5  查询第10页,每页显示5条(这里只要你不写size每页展示2条,写了定义的size就按你写的)
  max_page_size = 5  # 每页显示最大10条

img

方式二:偏移分页

# LimitOffset
class CommonLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3  # 每页显示2条
    limit_query_param = 'limit'  # limit=3   取3条
    offset_query_param = 'offset'  # offset=1  从第一个位置开始,取limit条
    max_limit = 5
    # offset=3&limit=2      0  1 2 3 4 5

img

方式三:游标分页

# app 用下面
游标分页,只能下一页,上一页
class CommonCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 查询参数
    page_size = 2  # 每页多少条
    ordering = 'id'  # 排序字段

img

以上方式一种配置在视图类上

# 配置在视图类上即可
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = []
    authentication_classes = []
    throttle_classes = []
    # 之前的东西一样用 ,内置的分页类不能直接使用,需要继承去定制一些参数后才能使用
    # pagination_class = PageNumberPagination
    #基本分页方式(基本是这种,网页端):http://127.0.0.1:8000/api/v1/books/?page=2&size=3

    # pagination_class = LimitOffsetPagination
    # 偏移分页 http://127.0.0.1:8000/api/v1/books/?limit=4&offset=1
    # 从第一条开始,取4条

    pagination_class = CommonCursorPagination
    # 游标分页,只能下一页,上一页,不能跳到中间,但它的效率最高,大数据量分页,使用这种较好
posted @ 2023-02-08 15:58  hugmi男孩  阅读(19)  评论(0)    收藏  举报