实战-DRF快速写接口(认证权限频率)
实战-DRF快速写接口
开发环境
- Python3.6
- Pycharm专业版2021.2.3
- Sqlite3
- Django 2.2
- djangorestframework3.13
测试工具
Postman
需求
- 注册接口,包含字段用户名,密码,确认密码,用户类型
- 登陆接口,校验用户名,密码,生成随机字符串
- 认证功能,除了注册登陆接口外,所有接口都要登陆后访问
- 频率限制功能,每分钟访问5次,book的所有接口,使用这个频率类
- 权限限制功能,publish的所有操作需要超级用户能访问,其他的普通登陆用户就可以操作
模型
from django.db import models
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=255)
user_type = models.IntegerField(choices=((1, '超级管理员'), (2, '普通管理员'), (3, '普通用户')))
class UserToken(models.Model):
user = models.OneToOneField(to=User,on_delete=models.CASCADE)
token = models.CharField(max_length=32)
class Book(models.Model):
title = models.CharField(max_length=11)
price = models.DecimalField(max_digits=5, decimal_places=2)
authors = models.ManyToManyField(to='Author')
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
@property
def publish_detail(self):
return {'name': self.publish.name,'Email':self.publish.email}
@property
def author_list(self):
l = []
print(self.authors.all()) # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
for author in self.authors.all():
print(author.authordetail) # AuthorDetail object (1)
l.append({'name': author.username, 'gender': author.gender,
'address': author.authordetail.address,'telephone':author.authordetail.telephone})
return l
class Author(models.Model):
username = models.CharField(max_length=11)
gender = models.IntegerField(choices=((1, '男'), (2, '女'), (3, '未知')))
authordetail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
@property
def authordetail_info(self):
return {'telephone': self.authordetail.telephone, 'address': self.authordetail.address}
class AuthorDetail(models.Model):
telephone = models.BigIntegerField()
address = models.CharField(max_length=32)
class Publish(models.Model):
name = models.CharField(max_length=11)
email = models.EmailField()
序列化器
from rest_framework import serializers
from .models import *
# 用户序列化器
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
# 书序列化器
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
# fields = '__all__'
fields = ['id', 'title', 'price', 'publish', 'authors', 'publish_detail', 'author_list']
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True},
}
# 作者序列化器
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
# 指定和哪个表有关系
model = Author
# fields = '__all__'
fields = ['id', 'username', 'gender', 'telephone', 'address', 'authordetail_info']
# 重写字段telephone和addr
telephone = serializers.CharField(write_only=True)
address = serializers.CharField(write_only=True, max_length=8, required=False)
# 重写create,操作两个表
def create(self, validated_data):
# 先存作者详情
authordetail = AuthorDetail.objects.create(telephone=validated_data.get('telephone'),
address=validated_data.get('address'))
# 存作者表
author = Author.objects.create(author_detail=authordetail, gender=validated_data.get('gender'),
username=validated_data.get('username'))
# 这样只返回author对象就行,直接存了两个表,返回反序列化的对象
return author
# 出版社序列化器
class PublishSerializer(serializers.ModelSerializer):
class Meta():
model = Publish
fields = '__all__'
视图
from django.contrib.auth.hashers import make_password, check_password
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from rest_framework.viewsets import ModelViewSet
from .auth import *
from .serializer import *
from .models import *
# 注册视图
class UserRegisterView(ViewSet):
@action(methods=["POST"], detail=False)
def register(self, request):
usernmae = request.data.get('username')
password = request.data.get('password')
re_password = request.data.get('re_password')
user_type = request.data.get('user_type')
if User.objects.filter(username=usernmae):
return Response({'msg': f'用户{usernmae}已注册!', 'code': 4000})
else:
if password == re_password:
# make_password加密:make_password(password, salt=None, hasher='default')
user_date = {'username': usernmae, 'password': make_password(password), 'user_type': user_type}
user_serializer = UserSerializer(data=user_date)
if user_serializer.is_valid():
user_serializer.save()
return Response({'code': 2001, 'msg': f'用户{usernmae}注册成功'})
else:
return Response({'code': 4001, 'msg': '注册失败', 'errors': user_serializer.errors})
else:
return Response({'msg': '两次密码不一致', 'code': 4002})
# 登录视图
class UserLoginView(ViewSet):
@action(methods=["POST"], detail=False)
def login(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(username=username).first()
# check_password(password, encoded, setter=None, preferred='default')
if user and check_password(password, user.password):
import uuid
token = str(uuid.uuid4())
UserToken.objects.update_or_create(user=user, defaults={'token': token})
return Response({'code': 2000, 'msg': f'用户{user.username}登录成功', 'token': token})
return Response({'code': 4004, 'msg': '校验失败,用户名或密码错误'})
# 书接视图
class BookView(ModelViewSet):
authentication_classes = [LoginAuth,]
throttle_classes = [IPThrottle,]
queryset = Book.objects.all()
serializer_class = BookSerializer
# 作者视图
class AuthorView(ModelViewSet):
authentication_classes = [LoginAuth,]
queryset = Author.objects.all()
serializer_class = AuthorSerializer
# 出版社视图
class PublishView(ModelViewSet):
authentication_classes = [LoginAuth, ]
permission_classes = [UserPermission,]
queryset = Publish.objects.all()
serializer_class = PublishSerializer
认证权限频率
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.permissions import BasePermission
from rest_framework.throttling import SimpleRateThrottle
from app01 import models
# 认证类
class LoginAuth(BaseAuthentication):
# 重写authenticate方法
def authenticate(self, request):
# 获取前端携带的token,token放在哪是自己规定的,比如从查询参数中获取
token = request.query_params.get('token')
# 比对随机字符串
user_token = models.UserToken.objects.filter(token=token).first()
if user_token:
# 登录了,返回当前登录用户和token
return user_token.user, token
else:
# 没有登录,抛异常
raise AuthenticationFailed('您没有登录,请登录')
# 权限类
class UserPermission(BasePermission):
def has_permission(self, request, view):
# 没有权限的提示信息
self.message = '您是:%s,没有权限' % request.user.get_user_type_display()
# 如果有权限,返回True,没有权限返回False
# 权限类,在认证类之后,request.user有了当前登录用户
user_type = request.user.user_type
print(user_type)
if user_type < 3: # 只要不是1,2,就没有权限
return True
else:
return False
# 频率类
class IPThrottle(SimpleRateThrottle):
scope = 'ip'
# get_cache_key返回什么就以什么方法做限制,限制条件必须唯一,比如用户id
def get_cache_key(self, request, view):
# 限制ip地址,从request.META字典中获取ip
'''
request.META:请求头中的数据
'''
return request.META.get('REMOTE_ADDR') # 客户端ip
配置文件
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'ip': '5/m' # minute_3是scope的字符串,一分钟访问5次
}, }
路由
from django.contrib import admin
from django.urls import path,include
from app01 import views
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('user',views.UserLoginView,'user')
router.register('user',views.UserRegisterView,'user')
router.register('books',views.BookView,'books')
router.register('author',views.AuthorView,'author')
router.register('publish',views.PublishView,'publish')
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(router.urls)),
]
测试
下面是普通用户,403了~
实战-DRF快速写接口(认证权限频率)的更多相关文章
- restful知识点之三restframework认证-->权限-->频率
认证.权限.频率是层层递进的关系 权限业务时认证+权限 频率业务时:认证+权限+频率 局部认证方式 from django.conf.urls import url,include from djan ...
- 8) drf 三大认证 认证 权限 频率
一.三大认证功能分析 1)APIView的 dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial(request, *ar ...
- rest framework 认证 权限 频率
认证组件 发生位置 APIview 类种的 dispatch 方法执行到 initial 方法 进行 认证组件认证 源码位置 rest_framework.authentication 源码内部需要 ...
- DRF-认证权限频率
目录 DRF-认证权限频率 认证 登录接口 认证 权限 作用 使用 频率 作用 使用 认证权限频率+五个接口 模型 视图 序列化器 认证权限频率类 配置文件 路由 DRF-认证权限频率 前后端混合开发 ...
- DRF-认证 权限 频率组件
补充 1 认证 权限 频率组件原理基本相同 2 认证相关: session cookie token 认证相关的 这里用token token 1 有时间限制,超时则失效 2 每次登录更换一个tok ...
- DRF 权限 频率
DRF的权限 权限是什么 大家之前都应该听过权限~那么我们权限到底是做什么用的呢~~ 大家都有博客~或者去一些论坛~一定知道管理员这个角色~ 比如我们申请博客的时候~一定要向管理员申请~也就是说管理员 ...
- DRF的版本、认证、权限
DRF的版本 版本控制是做什么用的, 我们为什么要用 首先我们要知道我们的版本是干嘛用的呢~~大家都知道我们开发项目是有多个版本的~~ 当我们项目越来越更新~版本就越来越多~~我们不可能新的版本出了~ ...
- DRF框架(七) ——三大认证组件之频率组件、jwt认证
drf频率组件源码 1.APIView的dispatch方法的 self.initial(request,*args,**kwargs) 点进去 2.self.check_throttles(re ...
- Spring Cloud实战: 基于Spring Cloud Gateway + vue-element-admin 实现的RBAC权限管理系统,实现网关对RESTful接口方法权限和自定义Vue指令对按钮权限的细粒度控制
一. 前言 信我的哈,明天过年. 这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT ...
随机推荐
- tensorflow源码解析之common_runtime-direct_session
目录 核心概念 direct_session direct_session.h direct_session.cc 1. 核心概念 读过之前文章的读者应该还记得,session是一个执行代理.我们把计 ...
- vue2.x结合echarts2实现显示具体省份热力图
最近研究了一下VUE2.X结合ehcarts实现热力图,先看下最终: 效果话不多说,直接上代码: 1 <!DOCTYPE html> 2 <html> 3 <head&g ...
- 通过Geth搭建私有以太坊网络
前言 为了进一步了解以太坊区块链网络的工作方式和运行原理,笔者通过官方软件Geth搭建了私有以太坊网络fantasynetwork,最终实现了单机和多机节点间的相互连通:首先通过VMware Work ...
- ansible 五 playbooks剧本使用
一.Playbook 简介 Playbooks与Ad-Hoc相比,是一种完全不同的运用Ansible的方式,而且是非常之强大的:也是系统ansible命令的集合,其利用yaml语言编写,运行过程,an ...
- 内网穿透工具--frp
对于没有公网 IP 的内网用户来说,远程管理或在外网访问内网机器上的服务是一个问题. 今天给大家介绍一款好用内网穿透工具 FRP,FRP 全名:Fast Reverse Proxy.FRP 是一个使用 ...
- 使用 Mosh 来优化 SSH 连接
1.什么是Mosh Mosh表示移动Shell(Mobile Shell),是一个用于从客户端跨互联网连接远程服务器的命令行工具.它能用于SSH连接,但是比Secure Shell功能更多.它是一个类 ...
- FOC软件中要处理的问题
1. 电流采样时间及通道 FOC需要通过采集相电流来进行控制,采样时间及通道极为关键,在二或三电阻采样方案中,采用如下方式: 在1.6扇区,B.C为采样通道: 在2.3扇区,A.C为采样通道: 在4. ...
- 【Python 第0课】Why Python?
为什么用Python作为编程入门语言? 原因很简单. 嗯...原因就是,很简单... 每种语言都会有它的支持者和反对者.去Google一下"why python"(程序员准则:要G ...
- SpringBoot bean映射yml中的属性举例
pom:导入配置文件处理器,配置文件进行绑定就会有提示 <dependency> <groupId>org.springframework.boot</groupId&g ...
- rabbitmq有哪些重要角色和组件?
rabbitmq有哪些重要角色? 生产者:消息的创建者,负责创建和推送数据到消息服务器 消费者:消息的接收方,用于处理数据和确认消息 代理:就是RabbitMQ本身,用于扮演快递的角色,本身并不生产消 ...