权限控制,即对已登录的用户进行访问权限的控制。
1.创建表:用户表UserInfo、token表 UserToken,权限表一 CommonVideo, 权限表二 VIPVideo
from django.db import models from datetime import datetime # Create your models here. class UserInfo(models.Model): """ 用户表 """ user_type_choices=( (1, "普通用户"), (2, "VIP"), (3, "SVIP") ) user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32) password = models.CharField(max_length=64) add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') class Meta: verbose_name = '用户表' verbose_name_plural = verbose_name def __str__(self): return self.username class UserToken(models.Model): """ Token表 """ user = models.ForeignKey(UserInfo, on_delete=models.CASCADE) token = models.CharField(max_length=64) add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') class Meta: verbose_name = 'token表' verbose_name_plural = verbose_name def __str__(self): return self.user.username class CommonVideo(models.Model): """ 普通视频 """ title = models.CharField(max_length=32) url = models.CharField(max_length=200, verbose_name='资源地址') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') class Meta: verbose_name = '普通视频表' verbose_name_plural = verbose_name def __str__(self): return self.title class VIPVideo(models.Model): """ 会员视频 """ title = models.CharField(max_length=32) url = models.CharField(max_length=200, verbose_name='资源地址') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') class Meta: verbose_name = '会员视频表' verbose_name_plural = verbose_name def __str__(self): return self.title
2.执行数据更新命令
python manage.py makemigration
python manage.py migrate
3.在UserInfo表中插入两条用户数据,user1 user_type=1, user2 user_type=2
4.分别在普通视频表和VIP视频表分别插入一条数据
5.安装Django REST Framework依赖
pip install djangorestframework markdown django-filter
6.settings文件添加配置
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', 'rest_framework', #新添加的配置 ] #新添加的配置 REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES':( 'app01.utils.auth.Authentication', ) }
7.在应用下,如设置的应用时app01,即在app01目录下新建一个utils目录,在该目录下新建一个auth.py文件,代码如下
from ..models import * from rest_framework import exceptions class Authentication(object): def authenticate(self, request): # 验证是否已经登录,函数名必须为:authenticate token = request._request.GET.get('token') token_obj = UserToken.objects.filter(token=token).first() print(token_obj) if not token_obj: raise exceptions.AuthenticationFailed('用户认证失败') # rest_framework内部会将以下元素赋值到request,以供后续使用 return (token_obj.user, token_obj) def authenticate_header(self, request): # 这个函数可以没有内容,但是必须要有这个函数 pass class VIP(object): """ 验证VIP权限 """ def has_permission(self, request, view): if request.user.user_type < 2: return False return True
8.在app01目录下新建序列化模块文件,serializers.py,代码如下:
from rest_framework import serializers from .models import CommonVideo, VIPVideo, SVIPVideo class CommonVideoSerializer(serializers.ModelSerializer): class Meta: model = CommonVideo fields = "__all__" class VIPVideoSerializer(serializers.ModelSerializer): class Meta: model = VIPVideo fields = "__all__" class SVIPVideoSerializer(serializers.ModelSerializer): class Meta: model = SVIPVideo fields = "__all__"
9.编写view.py的代码
from django.shortcuts import render from django.http import JsonResponse from rest_framework.views import APIView from .models import * from .serializers import * from rest_framework.response import Response from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer from rest_framework import exceptions from .utils.auth import Authentication from .utils.auth import VIP # Create your views here. def md5(user): import hashlib import time ctime = str(time.time()) m = hashlib.md5(bytes(user, encoding='utf-8')) m.update(bytes(ctime, encoding='utf-8')) return m.hexdigest() class AuthView(APIView): """ 登录 """ authentication_classes = [] def post(self, request): ret = {'code':1000, 'msg':'登录成功!'} try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = UserInfo.objects.filter(username=user, password=pwd).first() #print(user,pwd,obj) if not obj: ret['code'] = 1001 ret['msg'] = '用户名或密码错误' return JsonResponse(ret) #为登录用户创建token token = md5(user) #存在则更新,不存在的创建 UserToken.objects.update_or_create(user=obj, defaults={'token':token}) ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = '请求异常' return JsonResponse(ret) class Authentication(object): def authenticate(self, request): #验证是否已经登录,函数名必须为:authenticate token = request._request.GET.get('token') token_obj = UserToken.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed('用户认证失败') #在rest_framework内部会将以下两个元素赋值到request,以供后续使用 return (token_obj.user, token_obj) def authenticate_header(self, request): #这个函数可以没有内容,但是必须要有这个函数 pass class CommonVideoView(APIView): """ 登录后即可访问的内容资源 """ renderer_classes = [JSONRenderer] #渲染器 authentication_classes = [Authentication,] def get(self, request): video_list = CommonVideo.objects.all() re = CommonVideoSerializer(video_list, many=True) return Response(re.data) class VIPVideoView(APIView): """ VIP可访问的资源 """ renderer_classes = [JSONRenderer] #渲染器 permission_classes = [VIP,] def get(self, request): video_list = VIPVideo.objects.all() re = VIPVideoSerializer(video_list, many=True) print("***",video_list, re) return Response(re.data)
10.urls.py文件中添加路由
from django.contrib import admin from django.urls import path from app01.views import AuthView, CommonVideoView, VIPVideoView urlpatterns = [ path('admin/', admin.site.urls), path('auth/', AuthView.as_view(), name = 'auth'), path('common/', CommonVideoView.as_view(), name='common'), path('vip/', VIPVideoView.as_view(), name='vip'), ]
验证
1.使用postman,post请求登录user1
2.登录成功,使用登录成功返回的token访问common,返回commonVideo表数据信息,访问vip,提示无权限
3.使用postman,post请求登录user2
4.登录成功,使用登录成功返回的token访问common,返回commonVideo表数据信息,访问vip,返回VIPVideo表数据信息