1. 程式人生 > >Rest-framework之drf認證元件,許可權元件

Rest-framework之drf認證元件,許可權元件

  Rest-framework之drf認證元件,許可權元件

1.views檢視層

from django.shortcuts import render
from rest_framework.views import APIView
from app01 import models
from django.core.exceptions import ObjectDoesNotExist
import hashlib
import time
from django.http import JsonResponse
from app01 import MySerializer
from rest_framework.request import Request from rest_framework import exceptions def get_token(name): md5 = hashlib.md5() # 生成一個MD5物件 # 往裡新增值,必須是bytes格式 # time.time()生成時間戳型別,轉成字串,再encode轉成bytes格式 md5.update(str(time.time()).encode('utf-8')) md5.update(name.encode('utf-8'))
return md5.hexdigest() # 登入介面 class Login(APIView): authentication_classes = [] # 登入就是使用post,get是返回一個頁面 def post(self, request, *args, **kwargs): response = {'status': 100, 'msg': '登入成功'} name = request.data.get('name') pwd = request.data.get('pwd') try: user
= models.UserInfo.objects.get(name=name, pwd=pwd) # 校驗通過,登陸成功,就生成一個隨機字串(身份標識),token token = get_token(name) # 儲存到資料庫 # user=user就是需要查詢的資料,defaults裡面:token就是需要修改或者新增的資料 models.UserToken.objects.update_or_create(user=user, defaults={'token': token}) # 登陸成功之後把登入返回給他,以後就帶著token過來 response['token'] = token except ObjectDoesNotExist as e: response['status'] = 101 response['msg'] = '使用者名稱或密碼錯誤' except Exception as e: # 萬能異常,裡面只要出錯,程式就會走到這裡 response['status'] = 102 # response['msg'] = '未知錯誤' # 把整個錯誤資訊轉換成str型別,賦值給e,一般在測試時使用這個 response['msg'] = str(e) # 如果不寫safe=False,只能序列化字典形式,如果字典裡面又套了列表,或者直接是一個列表,就必須寫safe=False return JsonResponse(response, safe=False) from app01.MyAuth import LoginAuth class Books(APIView): # 列表中類名不能加括號 authentication_classes = [LoginAuth, ] def get(self, request, *args, **kwargs): # 只要通過認證,就能取到當前登入使用者物件的密碼,id等資訊 # print(request.query_params) # print(request.user.name) # print(request.user.pwd) response = {'status': 100, 'msg': '查詢成功'} res = models.Book.objects.all() book_ser = MySerializer.BookSerializer(res, many=True) # 這個資料是需要返回給前臺的 response['data'] = book_ser.data # print(book_ser.data) return JsonResponse(response, safe=False) # 需求:只能黃金會員才能檢視作者詳情,其他會員不能看 from app01.MyAuth import UserPermission class Authors(APIView): # permission_classes = [UserPermission,] # 區域性禁用 permission_classes = [] def get(self, request, *args, **kwargs): response = {'status': 100, 'msg': '查詢成功'} author_all = models.Author.objects.all() author_ser = MySerializer.AuthorSerializer(author_all, many=True) response['data'] = author_ser.data return JsonResponse(response, safe=False) class User(APIView): def get(self, request, *args, **kwargs): response = {'status': 100, 'msg': '查詢成功'} user_all = models.UserInfo.objects.all() user_ser = MySerializer.UserSerializer(user_all, many=True) response['data'] = user_ser.data return JsonResponse(response, safe=False)
View Code

2.MyAuth.py-認證元件和許可權元件

from app01 import models
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication


# 認證元件,使用drf的認證,我們需要寫一個類
class LoginAuth(BaseAuthentication):
    # 函式名一定要叫authenticate,需要接收2個引數,第二個引數是request物件
    def authenticate(self, request):
        # 從request物件中取出token(也可以從其他地方取)
        token = request.query_params.get('token')
        # 去資料庫過濾,查詢
        ret = models.UserToken.objects.filter(token=token).first()
        if ret:
            # 能查到,說明認證通過,反回空
            # ret.user就是當前登入使用者物件
            return ret.user, ret
        # 如果查不到,就丟擲異常
        raise exceptions.APIException('認證失敗')


#許可權元件,誰有資格檢視作者詳情資訊
class UserPermission():
    # message是錯誤顯示的中文
    message = '您沒有許可權檢視'

    def has_permission(self, request, view):
        user_type = request.user.user_type
        # print(user_type)
        # 取出使用者型別對應的文字
        # 固定用法:get_欄位名_display()
        user_type_name = request.user.get_user_type_display()
        print(user_type_name)
        if user_type == 2:
            return True
        else:
            return False
View Code

3.MySerializer.py-序列化元件

from rest_framework import serializers
from app01 import models


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'


class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Author
        fields = '__all__'


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = '__all__'

    user_type=serializers.CharField(source='get_user_type_display')
    # user_type = serializers.SerializerMethodField()

    # def get_user_type(self, obj):
    #     return obj.get_user_type_display()
View Code

4.models層

from django.db import models


# Create your models here.
# 使用者資訊
class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    # 寫choice
    user_choice = ((0, '普通會員'), (1, '鉑金會員'), (2, '黃金會員'))
    # 指定choice,可以快速的通過數字,取出文字
    user_type = models.IntegerField(choices=user_choice,default=0)


# 使用者token
class UserToken(models.Model):
    token = models.CharField(max_length=64)
    user = models.OneToOneField(to='UserInfo')


class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()

    publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE)  # 刪除關聯資料,與之關聯也刪除
    authors = models.ManyToManyField(to='Author')

    def __str__(self):
        return self.name


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDetail', to_field='nid', unique=True, on_delete=models.CASCADE)


class AuthorDetail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)

    def __str__(self):
        return self.telephone


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

    def __str__(self):
        return self.name

    def test(self):
        return self.email
View Code

5.settings.py

全域性使用認證和許可權
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.MyAuth.LoginAuth', ],
    'DEFAULT_PERMISSION_CLASSES': ['app01.MyAuth.UserPermission', ]
}

 6.urls.py路由層

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.Login.as_view()),
    url(r'^books/', views.Books.as_view()),
    url(r'^authors/', views.Authors.as_view()),
    url(r'^users/', views.User.as_view()),
]
View Code