首页 > 其他分享 >drf从入门到精通 07

drf从入门到精通 07

时间:2023-02-07 21:35:31浏览次数:45  
标签:入门 request queryset token objects user drf class 07

今日内容详细

认证组件

有些接口需要登录才能够访问 有些不需要登录就可以直接访问 由此引出来了认证组件

需求查看所有和创建无需登陆 其他需要登录

先写一个登录接口

class LoginView(ViewSet):

    @action(methods=['post'], detail=False)
    def login(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(name=username, pwd=password).first()
        if user:
            # 产生独一无二的token
            token = uuid.uuid4()
            UserToken.objects.update_or_create(user=user, defaults={'token': token})
            return Response({'code': 100, 'msg': '登陆成功', 'token': token})
        return Response({'code': 101, 'msg': '用户名或密码错误'})

    @action(methods=['post'], detail=False)
    def register(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(name=username).first()
        if not user:
            User.objects.create(name=username, pwd=password)
            return Response({'code': 100, 'msg': '注册成功'})
        return Response({'code': 101, 'msg': '用户以存在'})

认证组件的使用步骤
	1.先写一个认证类 继承BaseAuthentication
	2.重写authenticate方法 在该方法内编写认证 
	3.认证成功返回两个值  [当前登录用户, token]
	4.认证不成功抛出异常 AuthenticationFailed
	5.可以定义局部使用和全局使用
		局部: 直接在视图类中添加属性 authentication_classes = [认证类] 
		全局: 配置文件中添加
			REST_FRAMEWORK = {
            'DEFAULT_AUTHENTICATION_CLASSES':['认证类路径']
        }
		局部禁用: 在视图类中添加属性 authentication_classes = [] 

认证类
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import UserToken


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # token可以放在请求头中也可以放在url中
        token = request.META.get('HTTP_TOKEN')
        if token:
            user = UserToken.objects.filter(token=token).first()
            if user:
                # 如果存在则将登陆用户返回出去 以及token
                return user.user, token
            # 不存在则抛出异常
            raise AuthenticationFailed('token错误')
        raise AuthenticationFailed('token没传')

视图类
class BookView(ViewSetMixin, ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer



class BookDetailView(ViewSetMixin, RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    authentication_classes = [LoginAuth]

路由
from django.urls import path, include
from rest_framework import routers
from app01 import views

router = routers.SimpleRouter()
router.register('books', views.BookView, 'books')
router.register('books', views.BookDetailView, 'books')
router.register('user', views.LoginView, 'user')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include(router.urls)),
]

权限组件

即使登陆成功了 有些接口还是无法访问的 如视频网站 即使登陆了还是无法看vip视频 是因为设置了权限 通常权限就是数据库中的一个字段

需求
	查询所有和创建登陆用户都可以访问
	其他接口需要管理员才可以访问

权限组件使用步骤
	1.写一个权限类 继承BasePermission
	2.重写has_permission方法 在该方法中实现权限认证 并且在这里request.user就是当前登录用户
	3.有权限 返回True
	4.没有权限 返回False
	5.局部使用和全局使用
		局部: 直接在视图类中添加属性 permission_classes = [权限类] 
		全局: 配置文件中添加
			REST_FRAMEWORK = {
            'DEFAULT_PERMISSION_CLASSES':['权限类路径']
        }
		局部禁用: 在视图类中添加属性 permission_classes = [] 

权限类
from rest_framework.permissions import BasePermission


class CommonPermission(BasePermission):
    def has_permission(self, request, view):
        # 如果登录用户的权限字段为1 那么权限认证通过
        if request.user.user_type == 1:
            return True
        # 当权限认证不通过时 可以添加self.message属性 自定义提示内容
        self.message = f'您是{request.user.get_user_type_display()} 没有权限'
        return False

视图类
class BookView(ViewSetMixin, ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer



class BookDetailView(ViewSetMixin, RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    authentication_classes = [LoginAuth]
    permission_classes = [CommonPermission]

频率组件

用于控制接口访问的频率

频率组件使用步骤
	1.写一个频率类 继承SimpleRateThrottle
	2.重写get_cache_key方法 该方法返回啥 就以什么做限制
	3.配置一个类属性 scope = '随意起'
	4.在配置文件中配置
		REST_FRAMEWORK = {
            'DEFAULT_THROTTLE_RATES': {
                    '给scope取的名字': '次数/m', # 日时分秒都行d h m s
                },
        }
	5.局部使用和全局使用
		局部: 直接在视图类中添加属性 throttle_classes = [频率类] 
		全局: 配置文件中添加
			REST_FRAMEWORK = {
            'DEFAULT_THROTTLE_CLASSES':['频率类路径']
        }
		局部禁用: 在视图类中添加属性 throttle_classes = [] 

频率类
from rest_framework.throttling import SimpleRateThrottle


class CommonThrottle(SimpleRateThrottle):
    scope = 'throttle'

    def get_cache_key(self, request, view):
        # 这里返回的是客户端ip地址 那么就是以客户端ip地址访问的频率做限制
        return request.META.get('REMOTE_ADDR')

视图类
class BookView(ViewSetMixin, ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    throttle_classes = [CommonThrottle]


class BookDetailView(ViewSetMixin, RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    authentication_classes = [LoginAuth]
    permission_classes = [CommonPermission]
    throttle_classes = [CommonThrottle]

过滤排序

restful规范中 规定了请求地址中要带过滤条件
所有接口中 只有查询所有接口需要带过滤和排序

需求 查询以红开头的所有图书

方式一:
    使用内置的过滤类
    from rest_framework.filters import SearchFilter
    # 用法是固定的 只有模糊匹配
    
    class BookView(ViewSetMixin, ListAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
        # 指定过滤类
        filter_backends = [SearchFilter]
        # 按照指定字段模糊匹配
        search_fields = ['name','price']  # 可以按名字模糊匹配或价格模糊匹配

    查询方式
    	以url携带参数的形式 且参数名必须得是search
		如: http://127.0.0.1:8000/api/v1/books/?search=红
    
方式二:
    使用第三方django-filter实现
    pip3.8 install django-filter

    from django_filters.rest_framework import DjangoFilterBackend

    class BookView(ViewSetMixin, ListAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
        # 指定过滤类
        filter_backends = [DjangoFilterBackend]
        # 按照指定字段完整匹配
        filter_fields = ['name','price']  # 不是模糊匹配 而是完整匹配

    查询方式
    	以url携带参数的形式 参数名为指定字段名
    	如: http://127.0.0.1:8000/api/v1/books/?price=939&name=红楼梦 # 两个条件都得满足

方式三:
    自定义过滤类
    第一步:定义一个过滤类 继承BaseFilterBackend
    第二步:重写filter_queryset方法
    第三步:如果携带条件 那么返回对应结果
    第四步:没携带 那么返回所有数据

    过滤类
        class CommonFilter(BaseFilterBackend):
            def filter_queryset(self, request, queryset, view):
                # 在里面实现过滤,返回qs对象,就是过滤后的数据
                price_gt = request.query_params.get('price_gt')
                if price_gt:
                    qs = queryset.filter(price__gt=price_gt)
                    return qs
                return queryset

    视图类
        class BookView(ViewSetMixin, ListAPIView):
            queryset = Book.objects.all()
            serializer_class = BookSerializer

            filter_backends = [CommonFilter]  # 可以定制多个,从左往右,依次执行


排序
	使用内置的即可
    
from rest_framework.filters import OrderingFilter

class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [OrderingFilter]  
    ordering_fields = ['price', id]  # 指定字段

查询方法
	http://127.0.0.1:8000/api/v1/books/?ordering=price # 按照price正向排序
	http://127.0.0.1:8000/api/v1/books/?ordering=-price # 按照price反向排序
	http://127.0.0.1:8000/api/v1/books/?ordering=-price,id # 先按照id排倒叙 相同按id排

分页

分页,只有查询所有接口,才有分页
drf内置了三个分页器,对应三种分页方式
内置的分页类不能直接使用,需要继承,定制一些参数后才能使用

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination


#基本分页方式(基本是这种,网页端)
# 分页使用,自定义一个分页类(三种)
'''
page_size 每页数目
page_query_param 前端发送的页数关键字名,默认为”page”
page_size_query_param 前端发送的每页数目关键字名,默认为None
max_page_size 前端最多能设置的每页数量
'''
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条
    max_page_size = 5  # 每页最大显示5条


# 偏移分页 LimitOffset
'''
default_limit 默认限制,默认值与PAGE_SIZE设置一致
limit_query_param limit参数名,默认’limit’
offset_query_param offset参数名,默认’offset’
max_limit 最大limit限制,默认None
'''
class CommonLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 2  # 每页显示2条
    limit_query_param = 'limit'  # limit=3   取3条
    offset_query_param = 'offset'  # offset=1  从第一个位置开始,取limit条
    max_limit = 5		# 每页最多取5条


# app建议使用下面的方式
'''
cursor_query_param:默认查询字段,不需要修改
page_size:每页数目
ordering:按什么排序,需要指定
'''
class CommonCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 查询参数
    page_size = 2  # 每页多少条
    ordering = 'id'  # 排序字段
# 配置在视图类上即可
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    pagination_class = CommonCursorPagination # 分页与过滤等不一样 只能有一个分页方式 所以不传列表
    # 游标分页,只能下一页,上一页,不能跳到中间,但它的效率最高,大数据量分页,使用这种较好


注意!!!当排序与游标分页一起使用时 需要先排序在分页

如:http://127.0.0.1:8000/api/v1/books/ # 直接访问会报错
  http://127.0.0.1:8000/api/v1/books/?ordering=price # 需要先带排序条件才行

标签:入门,request,queryset,token,objects,user,drf,class,07
From: https://www.cnblogs.com/qian-yf/p/17099864.html

相关文章

  • drf从入门到飞升仙界 06
    模型类准备fromdjango.dbimportmodels#图书跟作者:多对多,需要建立中间表,但是我们可以通过ManyToManyField自动生成,写在哪里都行#图书跟出版社:一对多,一个出版社,出......
  • drf7
    今日内容概要认证组件权限组件频率组件过滤排序分页今日内容详细认证组件有些接口需要登录才能够访问有些不需要登录就可以直接访问由此引出来了认证组件需......
  • python之路65 drf从入门到成神 5 认证组件、权限组件、频率组件、过滤排序、分页
    认证组件以后,有的接口需要登录后才能访问,有的接口,不登录就能访问写一个登录接口,返回token,以后只要带着token过来,就是登录了不带就没有登录需求:查询所有不需要登录......
  • drf
    今日内容1.认证组件2.权限组件3.频率组件4.过滤排序5.分页1.认证组件认证组件使用步骤1.写一个认证类,继承BaseAuthentication2.重写authenticate方法,在该方法在中......
  • [openlayers07]——加载天地图为底图并展示GeoJSON
    [openlayers07]_加载天地图为底图并展示GeoJSON1.加载底图(得申请key)天地图2.创建地图、设置center和投影//创建地图constcenter=[114.1692,30.494];//EPSG:4......
  • drf-day7——认证组件、权限组件、频率组件、过滤排序、分页
    目录一、认证组件1.1登录接口1.2认证组件使用步骤1.3整体代码二、权限组件2.1需求分析:2.2权限的使用2.3代码三、频率组件3.1使用步骤3.2代码四、过滤排序4.0继承API......
  • DRF - 认证
    目录认证组件1.登录接口编写2.认证功能自定认证的使用步骤3.全局认证与局部认证、局部禁用(1)局部认证:对于对应的视图类生效(2)全局认证:对于全局的视图类生效(3)全局认证+局部......
  • DRF - 权限
    目录权限组件1.自定权限的使用步骤2.全局使用与局部使用(1)局部权限:对单独的视图类生效(2)全局权限:对于全局的视图类生效(3)全局权限+局部禁用3.代码演示permission.py-定制......
  • Linux编程入门
    GCCGNU编译器'-std=c99'表示指定编译标准安装sudoaptinstallgccg++查看版本gcc/g++-v/--version运行gcctest.c-oapp(编译)./app其中,app为自命名,可......
  • [SA记录] CF1073G Yet Another LCP Problem
    一开始刚看这题时感觉什么思路都没有,不过后来做完P4248[AHOI2013]差异和P7409SvT后再看感觉稍微好一点。这3道题都是SA+单调栈的套路。这一种套路看起来似乎基本都是处......