權(quán)限:判斷用戶(hù)有哪些訪問(wèn)數(shù)據(jù)的權(quán)限
-
由于認(rèn)證已經(jīng)完成畜伐,request內(nèi)就有了user對(duì)象既忆,當(dāng)前的登陸用戶(hù)
models.py
from django.db import models
# Create your models here.
from django.db import models
# Create your models here.
class Book(models.Model):
name=models.CharField(max_length=32)
price=models.DecimalField(max_digits=5,decimal_places=2)
publish=models.CharField(max_length=32)
class User(models.Model):
username=models.CharField(max_length=32)
password=models.CharField(max_length=32)
user_type=models.IntegerField(choices=((1,'超級(jí)用戶(hù)'),(2,'普通用戶(hù)'),(3,'二筆用戶(hù)')))
class UserToken(models.Model):
token=models.CharField(max_length=64)
user=models.OneToOneField(to=User,on_delete=models.CASCADE) #一對(duì)一關(guān)聯(lián)到User表
- ser.py
from rest_framework import serializers
from app01.models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model=Book
fields='__all__'
- views.py
from django.shortcuts import render
# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
import uuid
from rest_framework.request import Request
from app01 import models
class LoginView(APIView):
authentication_classes = []
def post(self,request):
username=request.data.get('username')
password=request.data.get('password')
user=models.User.objects.filter(username=username,password=password).first()
if user:
# 登陸成功,生成一個(gè)隨機(jī)字符串
token=uuid.uuid4()
# 存到UserToken表中
# models.UserToken.objects.create(token=token,user=user)# 用它每次登陸都會(huì)記錄一條韵洋,不好鸭津,如有有記錄
# update_or_create有就更新,沒(méi)有就新增
models.UserToken.objects.update_or_create(defaults={'token':token},user=user)
return Response({'status':100,'msg':'登陸成功','token':token})
else:
return Response({'status': 101, 'msg': '用戶(hù)名或密碼錯(cuò)誤'})
from app01 import app_auth
# 這個(gè)只有超級(jí)用戶(hù)可以訪問(wèn)
class TestView(APIView):
authentication_classes = [app_auth.MyAuthentication]
permission_classes = [app_auth.UserPermission]
def get(self,request,*args,**kwargs):
return Response('這是測(cè)試數(shù)據(jù)')
# 只要登錄用戶(hù)就可以訪問(wèn)
class TestView2(APIView):
authentication_classes = [app_auth.MyAuthentication]
def get(self,request,*args,**kwargs):
return Response('這是22222222測(cè)試數(shù)據(jù)')
# #演示內(nèi)置權(quán)限蚯舱,超級(jí)管理員可以查看
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication,BasicAuthentication
class TestView3(APIView):
authentication_classes=[SessionAuthentication,]
permission_classes = [IsAdminUser]
def get(self,request,*args,**kwargs):
return Response('這是22222222測(cè)試數(shù)據(jù),超級(jí)管理員可以看')
##解析組件
from rest_framework.parsers import MultiPartParser #傳文件的格式 formdata格式
## 頻率限制
from rest_framework.throttling import BaseThrottle
# test4 演示全局未登錄用戶(hù)訪問(wèn)頻次
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication,BasicAuthentication
class TestView4(APIView):
authentication_classes=[]
permission_classes = []
def get(self,request,*args,**kwargs):
return Response('我是未登錄用戶(hù)')
# test5 演示局部配置未登錄用戶(hù)訪問(wèn)頻次
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication,BasicAuthentication
from rest_framework.throttling import AnonRateThrottle
from app01.app_auth import MyAuthentication
class TestView5(APIView):
# authentication_classes=[MyAuthentication]
permission_classes = []
throttle_classes = [AnonRateThrottle]
def get(self,request,*args,**kwargs):
# 1/0
return Response('我是未登錄用戶(hù)掩蛤,TestView5')
# test6 演示登錄用戶(hù)每分鐘訪問(wèn)10次枉昏,未登錄用戶(hù)訪問(wèn)5次
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.throttling import AnonRateThrottle
from rest_framework.viewsets import ModelViewSet
class TestView6(APIView):
authentication_classes = [SessionAuthentication]
def get(self, request, *args, **kwargs):
return Response('我是未登錄用戶(hù),TestView6')
# 過(guò)濾組件的使用
from rest_framework.generics import GenericAPIView
from rest_framework.generics import ListAPIView
from app01.models import Book
from app01.ser import BookSerializer
class BookView(ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_fields = ('name','price')
# 排序組件的使用
from rest_framework.generics import ListAPIView
from rest_framework.filters import OrderingFilter
from app01.models import Book
from app01.ser import BookSerializer
class Book2View(ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [OrderingFilter]
ordering_fields = ('id', 'price')
#全局異常處理
from rest_framework.views import exception_handler
# 子定制返回對(duì)象
from app01.app_auth import APIResponse
class TestView7(APIView):
def get(self,request,*args,**kwargs):
return APIResponse(data={"name":'lqz'},token='dsafsdfa',aa='dsafdsafasfdee')
- app_auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app01.models import UserToken
class MyAuthentication(BaseAuthentication):
def authenticate(self, request):
# 認(rèn)證邏輯揍鸟,如果認(rèn)證通過(guò)乒验,返回兩個(gè)值
#如果認(rèn)證失敗扶平,拋出AuthenticationFailed異常
token=request.GET.get('token')
if token:
user_token=UserToken.objects.filter(token=token).first()
# 認(rèn)證通過(guò)
if user_token:
return user_token.user,token
else:
raise AuthenticationFailed('認(rèn)證失敗')
else:
raise AuthenticationFailed('請(qǐng)求地址中需要攜帶token')
from rest_framework.permissions import BasePermission
class UserPermission(BasePermission):
def has_permission(self, request, view):
# 不是超級(jí)用戶(hù),不能訪問(wèn)
# 由于認(rèn)證已經(jīng)過(guò)了,request內(nèi)就有user對(duì)象了揭朝,當(dāng)前登錄用戶(hù)
user=request.user # 當(dāng)前登錄用戶(hù)
# 如果該字段用了choice,通過(guò)get_字段名_display()就能取出choice后面的中文
print(user.get_user_type_display())
if user.user_type==1:
return True
else:
return False
# 自定義異常處理的方法
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
def my_exception_handler(exc, context):
response=exception_handler(exc, context)
# 兩種情況岩梳,一個(gè)是None尤慰,drf沒(méi)有處理
#response對(duì)象,django處理了蛔外,但是處理的不符合咱們的要求
# print(type(exc))
if not response:
if isinstance(exc, ZeroDivisionError):
return Response(data={'status': 777, 'msg': "除以0的錯(cuò)誤" + str(exc)}, status=status.HTTP_400_BAD_REQUEST)
return Response(data={'status':999,'msg':str(exc)},status=status.HTTP_400_BAD_REQUEST)
else:
# return response
return Response(data={'status':888,'msg':response.data.get('detail')},status=status.HTTP_400_BAD_REQUEST)
#自己封裝Response對(duì)象
from rest_framework.response import Response
# return APIResponse(100,'成功',data)
class APIResponse(Response):
def __init__(self,code=100,msg='成功',data=None,status=None,headers=None,**kwargs):
dic = {'code': code, 'msg': msg}
if data:
dic = {'code': code, 'msg': msg,'data':data}
dic.update(kwargs)
super().__init__(data=dic, status=status,headers=headers)
使用內(nèi)置的權(quán)限及登錄認(rèn)證
權(quán)限必須和認(rèn)證合起來(lái)用蛆楞,不然報(bào)錯(cuò)
使用了默認(rèn)的權(quán)限,就得使用默認(rèn)的認(rèn)證
-
自帶的權(quán)限與認(rèn)證
演示一下內(nèi)置權(quán)限的使用:IsAdminUser夹厌,控制是否對(duì)網(wǎng)站后臺(tái)有權(quán)限的人
1 創(chuàng)建超級(jí)管理員
命令行執(zhí)行:createsuperuser
2 寫(xiě)一個(gè)測(cè)試視圖類(lèi)
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication
class TestView3(APIView):
authentication_classes=[SessionAuthentication,]
permission_classes = [IsAdminUser] 判斷是否是超級(jí)管理員
def get(self,request,*args,**kwargs):
return Response('這是22222222測(cè)試數(shù)據(jù)豹爹,超級(jí)管理員可以看')
3 超級(jí)用戶(hù)登錄到admin,再訪問(wèn)test3就有權(quán)限
4 正常的話(huà)矛纹,普通管理員臂聋,沒(méi)有權(quán)限看(判斷的是is_staff字段)