首页 > 其他分享 >drf- 三大认证、排序

drf- 三大认证、排序

时间:2023-09-10 10:33:36浏览次数:34  
标签:get request token user import 排序 class 三大 drf

三大认证组件

登录认证

我们可以使用auth自带的User表,也可以选择自定义表.

写登录接口,登录成功要有标志,生成一个随机的字符串,放到表中,以后只要携带这个字符串就可以登录成功。
视图层
方法一:
class UserView(GenericViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserSerializer

    def login(self, request, *args, **kwargs):
        # 获取从前端传入的数据,并进行数据校验判断该用户是否存在,拿到的是QuerySet对象
        user_obj = self.get_queryset().filter(username=request.data.get("username"),password=request.data.get("password"))
        print(user_obj[0])
        # 判断用户是否存在
        if user_obj:
            # 存在获取一个UUID
            token = str(uuid.uuid4())
            # 通过用户对象查询Token表中是否存在一个Token对象,返回None或者一个对象
            user_taken = models.Token.objects.filter(usertoken=user_obj[0]).first()
            print(token, "++++++++")  # c03d3613-d4b7-4c17-abf6-eb82809fcfee ++++++++
            print(user_taken, "----------")  # Token object (1) ----------
            # 判断这个Token对象是否存在
            if user_taken:
                # 如果存在将得到的UUID的对象值赋值给Token表中的Token字段,后续可以使用这个字段开登录
                models.Token.token = token
                # 保存
                user_taken.save()
            else:
                # 如果这个Token对象不存在则给它添加一个
                models.Token.objects.create(token=token, usertoken_id=user_obj[0].pk)
            return Response({"code": 100, "msg": "登录成功", "username": user_obj[0].username, "token": token})
        else:
            return Response({"code": 101})
        
方法二:
	使用UserToken.objects.update_or_create(defaults={'token': token}, user=user)

class UserView(GenericViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserSerializer

    def login(self, request, *args, **kwargs):
        # 获取从前端传入的数据,并进行数据校验判断该用户是否存在,拿到的是QuerySet对象
        user_obj = self.get_queryset().filter(username=request.data.get("username"),password=request.data.get("password"))
        print(user_obj[0])
        # 判断用户是否存在
        if user_obj:
            # 存在获取一个UUID
            token = str(uuid.uuid4())
            Token.objects.update_or_create(defaults={"token": token}, usertoken=user_obj[0])
            return Response({"code": 100, "msg": "登录成功", "username": user_obj[0].username, "token": token})
        else:
            return Response({"code": 101, "msg": "账号或密码错误,请重新输入"})
路由层
urlpatterns = [
    path('register/', views.UserView.as_view({"post": "register"})),
    path('login/', views.UserView.as_view({"post": "login"})),

认证组件

认证的的作用:
	有些接口需要登陆以后才可以访问,没有登录的话就不能访问
    登录的接口就是为了限制某些接口的
    
认证类的使用:
	1、导入模块:from rest_framework.authentication import BaseAuthentication
    2、重写里面的    def authenticate(self, request):方法
    3、在authenticate中完成登录的认证,如果登录成功返回两个值,如果没登录抛出异常
    4、在视图类中局部使用
    
如果已经登录成功,可以在视图类中通过request.user拿到当前登录用户
使用方法
auth.py
1、新建一个auth.py文件用来专门做认证
2、在auth文件中写一个CBV继承BaseAuthentication,在里面重写def authenticate(self, request):方法
from rest_framework.authentication import BaseAuthentication
from .models import UserToken
from rest_framework.exceptions import AuthenticationFailed


class AuthUser(BaseAuthentication):
    def authenticate(self, request):
        # 获取从前端传入的token值
        token = request.GET.get("token")
        # 根据获得的token值查token表
        token_obj = UserToken.objects.filter(token=token).first()
        # 如果存在返回用户名以及token值
        if token_obj:
            return token_obj.user, token
        # 否则抛出异常
        else:
            raise AuthenticationFailed("您还没有登录")
视图层
from rest_framework.viewsets import ViewSet
from .models import User, UserToken
from rest_framework.response import Response
from rest_framework.decorators import action
from .auth import AuthUser
import uuid


# Create your views here.
class UserView(ViewSet):
    @action(methods=["POST"], detail=False)
    def login(self, request, *args, **kwargs):
        username = request.data.get("username")
        password = request.data.get("password")
        user = User.objects.filter(username=username, password=password).first()
        print(user)
        if user:
            token = str(uuid.uuid4())
            UserToken.objects.update_or_create(defaults={"token": token}, user=user)
            return Response({"code": 100, "msg": "登录成功", "username": user.username, "token": token})
        else:
            return Response({"code": 101, "msg": "登录失败"})


class PublishView(ViewSet):
    # 如果想要访问此视图函数必须先登录认证
    authentication_classes = [AuthUser] 

    def list(self, request):
        return Response("hhhh")
路由层
from django.contrib import admin
from django.urls import path, include
from app_one.views import UserView, PublishView
from rest_framework.routers import SimpleRouter

render = SimpleRouter()
render.register("user", UserView, "user")
render.register("publish", PublishView, "publish")

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(render.urls)),
]

小结
 1、先写好认证类
    -局部使用------>配置在视图类中:authentication_classes = [AuthUser]
    -全局使用:
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': [
            'app01.auth.LoginAuth'
        ],
    }
    -局部禁用------>在视图类中配置:authentication_classes = []

写认证类:
	-一定要重写authenticate方法,否则会抛异常,必须要返回两个参数:当前登录用户user_token.user,用户的 token
    -认证类返回的第一个参数---->request.user
    -认证类返回的第二个参数---->request.auth
    
    -认证失败主动抛出异常抛AuthenticationFailed,会被drf捕捉到并做处理,不会在前端报错
    
    -前端传入的token值从哪里取?
    	-在url中:request.GET()/request.query_params.get()
        -请求头:request.META.get('HTTP_TOKEN')属性来获取请求头中的数据
        -请求体:request.data

权限组件

在系统中:有超级用户、有普通用户、有管理员用户,他们都登陆过了,有分权限,就像普通用户只能访问部分功能, 超级管理员则是可以访问全部功能
使用步骤
from rest_framework.permissions import BasePermission
1、写一个类,继承BasePermission
2、重写has_permission
3、在方法中校验用户是否有权限,如果有,就返回True,如果没有,就返回False
	-由于它的执行是在认证之后,所有从request.user中取出当前等用户,判断权限
    
4、局部使用,在视图类中----->permission_classes = [Permissions]

5、全局使用,在配置文件中:
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': [
            'app01.auth.LoginAuth'
        ],
        'DEFAULT_PERMISSION_CLASSES': [
            'app01.permissions.Permissions',
        ],
}
permission类
from rest_framework.permissions import BasePermission

1 写一个类,继承 BasePermission
2 重写 has_permission
3 在方法中校验用户是否有权限,如果有,就返回True,如果没有,就返回False

class Permissions(BasePermission):
    def has_permission(self, request, view):
        # request 当次请求的request,  新的,它是在认证类之后执行的,如果认证通过了request.user 就是当前登录用户
        # 拿到当前登录用户,查看它的类型,确定有没有权限
        print(request.__dict__)
        if request.user.user_type == 3:
            return True

        else:
            self.message = "您的用户类型是%s,您没有权限访问该功能" % (request.user.get_user_type_display())
            return False
视图类
class PublishView(ViewSet):
    # 如果未登录无法访问该接口
    authentication_classes = [AuthUser]
    # 如果权限不够无法访问该接口
    permission_classes = [Permissions]

    def list(self, request):
        return Response("hhhh")
路由类
from rest_framework.routers import SimpleRouter

render = SimpleRouter()
render.register("user", UserView, "user")
render.register("publish", PublishView, "publish")

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(render.urls)),
]

Django项目国际化

# 配置文件中--->以后所有英文都会转成中文
INSTALLED_APPS = [
    'rest_framework'
]

LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False

频率组件

作用:
	控制一个接口的访问频次,譬如每分钟只可以访问一次等等
    对接口进行访问次数限制
    
使用步骤:
	1、写一个类继承SimpleRateThrottle
    2、重写get_cache_key,返回什么,就以什么做限制:
    	-IP地址
        -用户id限制
    3、写一个类属性:
    	scope = 'XXX'
     4、在配置文件中进行配置:
        '''
            'DEFAULT_THROTTLE_RATES': {
                'drf_day08': '3/m',  # 一分钟访问三次   		5/s,m,h,d,/秒/分/时/天
            },
        '''
        
    5、局部使用、全局使用,局部禁用:
    	-局部使用:throttle_classes = [IPRateThrottle]
        -全局使用:
        'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.IPRateThrottle'],
throttle
from rest_framework.throttling import SimpleRateThrottle


class IPRateThrottle(SimpleRateThrottle):
    # 必须要自定义一个属性,值可以任意命名
    scope = "Wayyy"
	# 重写get_cache_key方法
    def get_cache_key(self, request, view):
        return request.META.get("REMOTE_ADDR")
配置文件中配置
'DEFAULT_THROTTLE_RATES': {
    'Wayyy': '3/m',  # 一分钟访问三次
},
视图文件
class PublishView(ViewSet):
    # 如果未登录无法访问该接口
    authentication_classes = [AuthUser]
    # 如果权限不够无法访问该接口
    permission_classes = [Permissions]

    throttle_classes = [IPRateThrottle]

    def list(self, request):
        return Response("hhhh")

排序

什么时候用?
	涉及到查询所有数据的时候
 
# 使用步骤
    - 1 必须写在继承:GenericAPIView 类的视图类中才行
    -2 配置类属性:
    filter_backends = [OrderingFilter]
    ordering_fields=['id','user_type'] #可以排序的字段

    -3 使用
    http://127.0.0.1:8000/user/?ordering=user_type #用户类型升序排
            http://127.0.0.1:8000/user/?ordering=-user_type #用户类型降序排
                    http://127.0.0.1:8000/user/?ordering=user_type,-id#先按用户类型升序排,如果用户类型一样,再按id降序排

作业

# 1 认证类
	-token从 请求头中取 ----->request.META
    -token从 请求体中取 ----->request.data.get("tokenk")
    
# 2 编写权限类
# 4 编写频率类,以用户id限制,一分钟只能访问5次

# 5 编写books5个接口,所有接口必须登录后才能访问,限制普通登录用户只能查看所有和新增一条,超级用户能查看一条,删除,修改

# 6 对查询所有图书接口可以按price和id排序

编写books5个接口,所有接口必须登录后才能访问,限制普通登录用户只能查看所有和新增一条,超级用户能查看一条,删除,修改
视图类
class CatBookView(ViewSetMixin, ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers
    authentication_classes = [AuthUser]
    permission_classes = [Permissions]
    throttle_classes = [IPRateThrottle]


class UpdateBookView(ViewSetMixin, RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers
    authentication_classes = [AuthUser]
    permission_classes = [Permissions]
    throttle_classes = [IPRateThrottle]
auth类
from rest_framework.authentication import BaseAuthentication
from .models import UserToken
from rest_framework.exceptions import AuthenticationFailed


class AuthUser(BaseAuthentication):
    def authenticate(self, request):
        token = request.GET.get("token")
        # print(request.META)
        # print(request.headers)
        token_obj = UserToken.objects.filter(token=token).first()
        if token_obj:
            return token_obj.user, token
        else:
            raise AuthenticationFailed("您还没有登录")
permissions类
from rest_framework.permissions import BasePermission


class Permissions(BasePermission):
    def has_permission(self, request, view):
        # print(request.__dict__)
        if request.user.user_type == 3:
            return True

        else:
            self.message = "您的用户类型是%s,您没有权限访问该功能" % (request.user.get_user_type_display())
            return False

throttle类
from rest_framework.throttling import SimpleRateThrottle


class IPRateThrottle(SimpleRateThrottle):
    scope = "Wayyy"

    def get_cache_key(self, request, view):
        token = request.GET.get("token")
        user_id = request.user.pk
        return f"{self.scope}:{token}:{user_id}"
序列化类
from rest_framework import serializers
from .models import Book


class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"
路由层
from django.contrib import admin
from django.urls import path, include
from app_one.views import CatBookView, UpdateBookView
from rest_framework.routers import SimpleRouter

render = SimpleRouter()
render.register("books", CatBookView, "books")
render.register("book", UpdateBookView, "book")

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(render.urls)),
]

标签:get,request,token,user,import,排序,class,三大,drf
From: https://www.cnblogs.com/chao0308/p/17690856.html

相关文章

  • es排序
    ......
  • C#希尔排序算法
    前言希尔排序简单的来说就是一种改进的插入排序算法,它通过将待排序的元素分成若干个子序列,然后对每个子序列进行插入排序,最终逐步缩小子序列的间隔,直到整个序列变得有序。希尔排序的主要思想是通过插入排序的优势,减小逆序对的距离,从而提高排序效率。希尔排序实现原理首先要确......
  • 排序总结 链表
    排序总结时间复杂度空间复杂度是否能有稳定性选择O(N*N)O(1)×冒泡O(N*N)O(1)✔️插入O(N*N)O(1)✔️归并O(N*logN)O(N)✔️快排(一般指3.0)O(N*logN)O(N*logN)×堆O(N*logN)O(1)×基数排序作为不基于比较的排序,有稳定性基础类型的排序一般排序用快排,因为其时间复杂度常数项更小,需要保持......
  • 解析排序算法:十大排序方法的工作原理与性能比较
    当我们面临对数据进行排序的任务时,计算机科学家们开发了多种排序算法来满足不同的需求。这些排序算法各具特点,适用于不同规模和类型的数据集。在本文中,我们将介绍十大常见的排序算法,并讨论它们的工作原理、时间复杂度以及适用场景。1.冒泡排序(BubbleSort)冒泡排序是最简单的排序算......
  • LeetCode -- 207. 课程表 (拓扑排序)
     经典拓扑排序的应用,用拓扑排序的算法看看原图中是否有一个合法的拓扑序。classSolution{public:conststaticintN=2010,M=5010;inth[N],e[M],ne[M],idx;intd[N],q[N];voidadd(inta,intb){e[idx]=b,ne[idx]=h[a],h[......
  • 接口文档、jwt介绍和构成、jwt签发和认证、base64编码、drf-jwt编码、drf-jwt使用
    接口文档作为后端,接口写好了,需要编写接口文档作为前端,需要使用后端写的接口(移动端、web桌面端),可以照着接口文档写接口文档的展现形式:1.word、md,写好传到公司的某个平台===》前端可以下载使用2.自动生成接口文档===》后端通过配置===》把所写的接口都自动生成===》......
  • 2039:【例5.6】冒泡排序
    2039:【例5.6】冒泡排序时间限制:1000ms      内存限制:65536KB提交数:51543   通过数:28200【题目描述】编程输入n(1≤n≤20)(1≤n≤20)个小于10001000非负整数,然后自动按从大到小的顺序输出。(冒泡排序)【输入】第一行,数的个数n;第二行,n个非负整数。......
  • 接口文档,jwt介绍和构成,jwt签发与认证,base64编码,drf-jwt使用,django-rest-framewor
    1接口文档#作为后端,接口写好了#作为前端,需要使用我们写的接口(移动端,web,桌面端)#后端需要写接口文档#接口文档的展现形式: 1word,md,写好传到公司的某个平台---》前端可以下载2自动生成接口文档---》后端通过配置--》把所写的接口都自动生成---》地址--》访问......
  • drf-jwt使用
    一、jwt介绍和构成1.介绍jwt:JsonWebToken,Web方向的Token认证方案在用户注册或登录之后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证(token串)。我们不再使用session认证机制,而使用JsonWebToken(本质就是token)认证机制。JsonWebToken:JWT用在我们前后端......
  • JavaNote04-数组与排序算法
    1.数组的概述1.1数组的概念数组(Array)是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。数组中的概念:数组名、下标(或索引)、元素、数组的长度数组的特点:数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基......