django 之(四) --- 级联|截流
登陆注册
登陆注册实现
- settings.py
# redis配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"TIMEOUT": 60 * 60 * 24,
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
- App/models.py
from django.db import models class UserModel(models.Model):
u_name = models.CharField(max_length=16, unique=True)
u_password = models.CharField(max_length=256) def __str__(self):
return self.u_name
- App/serializers.py
from rest_framework import serializers
from App.models import UserModel, Address class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = UserModel
fields = ('url', 'id', 'u_name', 'u_password', 'address_list')
- App/views.py
import uuid
from django.core.cache import cache
from rest_framework import exceptions
from rest_framework.generics import CreateAPIView, RetrieveAPIView
from rest_framework.response import Response
from App.models import UserModel
from App.serializers import UserSerializer # 继承自CreateAPIView。。exceptions框架封装的状态码变量包文件
class UsersAPIView(CreateAPIView):
serializer_class = UserSerializer
queryset = UserModel.objects.all() # 重写post,获取其action动作
def post(self, request, *args, **kwargs):
action = request.query_params.get('action')
if action == "login": # 登陆动作
u_name = request.data.get('u_name')
u_password = request.data.get('u_password')
try:
user = UserModel.objects.get(u_name=u_name)
if user.u_password != u_password:
raise exceptions.AuthenticationFailed
token = uuid.uuid4().hex
cache.set(token, user.id, timeout=60 * 60 * 24)
data = {
'msg': 'login success',
'status': 200,
'token': token
}
return Response(data)
except UserModel.DoesNotExist:
raise exceptions.NotFound
elif action == "register": # 注册动作
return self.create(request, *args, **kwargs)
else:
raise exceptions.ParseError # 继承自RetrieveAPIView。
class UserAPIView(RetrieveAPIView):
serializer_class = UserSerializer
queryset = UserModel.objects.all()
- urls.py 和 App/urls.py
from django.conf.urls import url, include urlpatterns = [
url(r'^app/', include('App.urls')),
]
#------------------------------------------------------------------------------------------ from django.conf.urls import url
from App import views urlpatterns = [
url(r'^users/$', views.UsersAPIView.as_view()),
# 继承自序列化HyperlinkedModelSerializer。需要加详情信息的url
url(r'^users/(?P<pk>\d+)/$', views.UserAPIView.as_view(), name='usermodel-detail'), ]
用户地址
登陆用户对地址添加
- App/models.py
from django.db import models class UserModel(models.Model):
u_name = models.CharField(max_length=16, unique=True)
u_password = models.CharField(max_length=256) def __str__(self):
return self.u_name class Address(models.Model):
a_address = models.CharField(max_length=128)
a_user = models.ForeignKey(UserModel, related_name='address_list', null=True, blank=True) def __str__(self):
return self.a_address
- App/serializers.py
from rest_framework import serializers
from App.models import UserModel, Address class AddressSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Address
fields = ('url', 'id', 'a_address') class UserSerializer(serializers.HyperlinkedModelSerializer):
address_list = AddressSerializer(many=True, read_only=True) class Meta:
model = UserModel
fields = ('url', 'id', 'u_name', 'u_password', 'address_list')
- App/views.py
import uuid
from django.core.cache import cache
from rest_framework import exceptions
from rest_framework.generics import CreateAPIView, RetrieveAPIView
from rest_framework.response import Response
from rest_framework import viewsets
from App.auth import LoginAuthentication
from App.models import UserModel, Address
from App.permissions import RequireLoginPermission
from App.serializers import UserSerializer, AddressSerializer # 继承自CreateAPIView。。exceptions框架封装的状态码变量包文件
class UsersAPIView(CreateAPIView):
serializer_class = UserSerializer
queryset = UserModel.objects.all() # 重写post,获取其action动作
def post(self, request, *args, **kwargs):
action = request.query_params.get('action')
if action == "login": # 登陆动作
u_name = request.data.get('u_name')
u_password = request.data.get('u_password')
try:
user = UserModel.objects.get(u_name=u_name)
if user.u_password != u_password:
raise exceptions.AuthenticationFailed
token = uuid.uuid4().hex
cache.set(token, user.id, timeout=60 * 60 * 24)
data = {
'msg': 'login success',
'status': 200,
'token': token
}
return Response(data)
except UserModel.DoesNotExist:
raise exceptions.NotFound
elif action == "register": # 注册动作
return self.create(request, *args, **kwargs)
else:
raise exceptions.ParseError # 继承自RetrieveAPIView
class UserAPIView(RetrieveAPIView):
serializer_class = UserSerializer
queryset = UserModel.objects.all() class AddressAPIView(viewsets.ModelViewSet):
serializer_class = AddressSerializer
queryset = Address.objects.all()
# 登陆认证。判断用户是否登陆成功的
authentication_classes = (LoginAuthentication,)
# 权限认证。只有登陆的用户才有权限
permission_classes = (RequireLoginPermission,)
- App/auth
# 登陆认证。判断用户是否是登陆状态、是否是合法用户
from django.core.cache import cache
from rest_framework.authentication import BaseAuthentication
from App.models import UserModel # 登陆认证器。继承自BaseAuthentication
class LoginAuthentication(BaseAuthentication): def authenticate(self, request):
try:
token = request.query_params.get('token')
user_id = cache.get(token)
user = UserModel.objects.get(pk=user_id)
return user, token
except Exception:
return
- App/permissions.py
# 权限认证。只有登陆用户的对象是此模型类的实例才有权限对地址信息进行操作
from rest_framework.permissions import BasePermission
from App.models import UserModel class RequireLoginPermission(BasePermission):
# 重写has_permission方法,判断是否有权限
def has_permission(self, request, view):
# isinstance判断此用户是否是此模型的实例。如果是返回True;不是返回False
return isinstance(request.user, UserModel)
- urls.py 和 App/urls.py
from django.conf.urls import url
from App import views urlpatterns = [
url(r'^users/$', views.UsersAPIView.as_view()),
# 继承自序列化HyperlinkedModelSerializer。需要加详情的url
url(r'^users/(?P<pk>\d+)/$', views.UserAPIView.as_view(), name='usermodel-detail'), # 视图类继承自viewsets.ModelViewSet。
url(r'^address/$', views.AddressAPIView.as_view(
{
'post': 'create', # 参数:post对应create类方法
'get': 'list', # 参数:get对应list类方法
}
)),
# 继承自序列化HyperlinkedModelSerializer。需要加详情的url
url(r'^address/(?P<pk>\d+)/$', views.AddressAPIView.as_view(
{
'get': 'retrieve',
}
), name='address-detail'),
]
查询操作
认证登陆用户权限查询
- App/views.py
import uuid
from django.core.cache import cache
from rest_framework import exceptions, status
from rest_framework.generics import CreateAPIView, RetrieveAPIView
from rest_framework.response import Response
from rest_framework import viewsets
from App.auth import LoginAuthentication
from App.models import UserModel, Address
from App.permissions import RequireLoginPermission
from App.serializers import UserSerializer, AddressSerializer # 继承自CreateAPIView。。exceptions框架封装的状态码变量包文件
class UsersAPIView(CreateAPIView):
serializer_class = UserSerializer
queryset = UserModel.objects.all() # 重写post,获取其action动作
def post(self, request, *args, **kwargs):
action = request.query_params.get('action')
if action == "login": # 登陆动作
u_name = request.data.get('u_name')
u_password = request.data.get('u_password')
try:
user = UserModel.objects.get(u_name=u_name)
if user.u_password != u_password:
raise exceptions.AuthenticationFailed
token = uuid.uuid4().hex
cache.set(token, user.id, timeout=60 * 60 * 24)
data = {
'msg': 'login success',
'status': 200,
'token': token
}
return Response(data)
except UserModel.DoesNotExist:
raise exceptions.NotFound
elif action == "register": # 注册动作
return self.create(request, *args, **kwargs)
else:
raise exceptions.ParseError # 继承自RetrieveAPIView
class UserAPIView(RetrieveAPIView):
serializer_class = UserSerializer
queryset = UserModel.objects.all() class AddressAPIView(viewsets.ModelViewSet):
serializer_class = AddressSerializer
queryset = Address.objects.all()
# 登陆认证
authentication_classes = (LoginAuthentication,)
# 权限认证
permission_classes = (RequireLoginPermission,) # 重写create。地址信息关联用户
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
# 对用户和地址进行绑定操作
user = request.user
a_id = serializer.data.get('id')
address = Address.objects.get(pk=a_id)
address.a_user = user
address.save()
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
# 重写list方法。实现get请求时只显示当前用户对应的地址信息的及联操作
def list(self, request, *args, **kwargs):# 根据用户查询地址信息。其他代码都是源码内容
queryset = self.filter_queryset(self.queryset.filter(a_user=request.user)) page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
# 继承自RetrieveAPIView。用户信息查询,只有登陆认证的用户才可以查看自己的信息
class UserAPIView(RetrieveAPIView):
serializer_class = UserSerializer
queryset = UserModel.objects.all() 6 authentication_classes = (LoginAuthentication,)
7 permission_classes = (RequireLoginPermission,) # 判定是本人。登陆认证后,只能查看自己的信息。[限制请求接口:路径里面的参数和用户是同一个用户才可查询]
def retrieve(self, request, *args, **kwargs):
if kwargs.get('pk') != str(request.user.id):
raise exceptions.AuthenticationFailed
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
及联查询
- 路由url:http://127.0.0.1:8000/app/users/1/?token=7fc732d30b5e4f5ebfde8e59e1938e22
- App/models.py
from django.db import models class UserModel(models.Model):
u_name = models.CharField(max_length=16, unique=True)
u_password = models.CharField(max_length=256) def __str__(self):
return self.u_name class Address(models.Model):
a_address = models.CharField(max_length=128)
a_user = models.ForeignKey(UserModel, related_name='address_list', null=True, blank=True) def __str__(self):
return self.a_address
- App/serializers.py
from rest_framework import serializers
from App.models import UserModel, Address class AddressSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Address
fields = ('url', 'id', 'a_address')
8 # 及联操作。
class UserSerializer(serializers.HyperlinkedModelSerializer):
# 此处变量名要和模型中related_name='address_list'定义的名字对应。
# 如果模型中没有定义related_name字段,默认系统识别的名字是address_set
address_list = AddressSerializer(many=True, read_only=True) class Meta:
model = UserModel
fields = ('url', 'id', 'u_name', 'u_password', 'address_list')
截流控制 [频率控制]
- settings.py 截流注册。配置全局截流,若想对某一个类视图截流,可以在此视图中设置
# 配置全局截流
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES": (
# 限制用户的频率。用户类名
"App.throttles.UserThrottle",
# 限制游客的频率:AnonRateThrottle
),
# 限制的【频率
"DEFAULT_THROTTLE_RATES": {
"user": "5/m", # 登陆的用户每分钟5次
}
}
- App/throttles 自定义截流
from rest_framework.throttling import SimpleRateThrottle
from App.models import UserModel class UserThrottle(SimpleRateThrottle):
scope = 'user' def get_cache_key(self, request, view):
if isinstance(request.user, UserModel):
ident = request.auth
else:
ident = self.get_ident(request) return self.cache_format % {
'scope': self.scope,
'ident': ident
}
HTTP_X_FORWARDED_FOR:获取你的原始IP,通过的普通的代理发送请求的请求;如果获取REMOTE_ADDR获取到的是代理IP
截流器源码分析
节流器
BaseThrottle
allow_request:[抽象未实现]是否允许的请求的核心
get_ident:获取客户端唯一标识
- wait:默认是None
SimpleRateThrottle
get_cache_key:获取缓存标识
get_rate:获取频率
parse_rate:转换频率。num/duration[s、m、h、d]
allow_request:是否允许请求,重写的方法
throttle_success:允许请求,进行请求记录
throttle_failure:不允许请求
wait:还有多少时间之后允许
AnonRateThrottle
get_cache_key:获取缓存key的原则
UserRateThrottle
和上面一模一样
ScopedRateThrottle
和上面一样。多写了从属性中获取频率
django 之(四) --- 级联|截流的更多相关文章
- python学习笔记--Django入门四 管理站点--二
接上一节 python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...
- django第四天(路由别名,django2.x新特性和自定义转换器)
django第四天 路由别名 1.路由别名: 给路由路径命名一个名字 url(r'^login/$',views.login,name = 'login') 2.为什么要用路由别名 ①当路由路径过长时 ...
- Django - Xadmin (四) Filter
Django - Xadmin (四) Filter Filter 功能描述 与 admin 组件中 Filter 功能类似,在展示页面右侧放置一列标签,通过点击这些标签来筛选出该标签相关的数据. 比 ...
- day 68 Django基础四之模板系统
Django基础四之模板系统 本节目录 一 语法 二 变量 三 过滤器 四 标签Tags 五 模板继承 六 组件 七 自定义标签和过滤器 八 静态文件相关 一 语法 模板渲染的官方文档 关 ...
- day 54 Django基础四之模板系统
Django基础四之模板系统 本节目录 一 语法 二 变量 三 过滤器 四 标签Tags 五 模板继承 六 组件 七 自定义标签和过滤器 八 静态文件相关 一 语法 模板渲染的官方文档 关于模 ...
- Django基础四之测试环境和ORM查询
Django基础四之测试环境和ORM查询 目录 Django基础四之测试环境和ORM查询 1. 搭建测试环境 1.1 测试环境搭建方法: 1.2 使用测试环境对数据库进行CURD 1.3 返回Quer ...
- 【Python】Django数据模型、级联删除、级联更新、ER图导出等
在本文中,我们将向读者详细介绍如何在更新和删除父表数据的同时,触发有关子表数据的级联更新和删除操作.您将看到当使用InnoDB表的时候,借助于外键约束就可以轻松搞定这一过程. 一.利用外键约束更新并删 ...
- 小白学习django第四站-关联数据库
使用mysql连接django首先要配置好相关环境 首先在setting.py配置数据库信息(需要现在mysql中创建一个数据库) 在setting.py那个目录的__init__.py文件中写入 之 ...
- Django(四)
一.请求周期 url> 路由 > 函数或类 > 返回字符串或者模板语言? 1.Form表单提交: 提交 -> url > 函数或类中的方法 - .... HttpResp ...
随机推荐
- Oracle 多表联合删除?--转
oracle和mysql多表删除数据的方法一大把,好多都是没经过证实的,你很可能已经被错误信息误导了,下面我以mysql两张表删除数据为例,来让给为注意到这一点,我在mysql中新建了两张表,分别是用 ...
- 第81题:搜索旋转排序数组II
一. 问题描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] ). 编写一个函数来判断给定的目标值是 ...
- vue 想关工具 及组件
vue-cli vue的脚手架工具 (1) 安装通过 npm install -g vue-cil (2)常用模板 browserify - 拥有高级功能的 Browserify ...
- string::at
char& at (size_t pos); const char& at (size_t pos) const; #include <string>#include &l ...
- SIGAI深度学习第三集 人工神经网络2
讲授神经网络的理论解释.实现细节包括输入与输出值的设定.网络规模.激活函数.损失函数.初始化.正则化.学习率的设定.实际应用等 大纲: 实验环节: 理论层面的解释:两个方面,1.数学角度,映射函数h( ...
- React项目性能优化
1. 使用生产版本和Fragment 1. 生产版本 确保发布的代码是生产模式下(压缩)打包的代码. 一般运行npm run build命令. 直接从webpack看配置文件,需要设置mode = ' ...
- 五十七.分布式ELK平台、ES安装 、 扩展插件 、Kibana安装
1. ES集群安装 准备1台虚拟机 部署elasticsearch第一个节点 访问9200端口查看是否安装成功 1ELK是日志分析平台,不是一款软件,而是一整套解决方案,是三个软件产品的首字母缩写 ...
- 五十一.Openstack概述 部署安装环境 、 部署Openstack OpenStack操作基础
虚拟化技术的底层构成: 内核的虚拟化模块(KVM):从内核集去提供虚拟化及CPU指令集的支持,要求CPU支持,(CPU有VMX指令集) 硬件仿真层(QEMU):虚拟一些周边设备,鼠标.键盘.网卡. ...
- Web service stop after running serveral hours
Error Message: 1. Error:Web service call "Test" execution failed 2. Error:<CENTER>&l ...
- Mac下Maven的删除和安装
一 删除maven 找到当前的maven路劲:使用mvn -v查看当前maven的安装目录在哪 删掉sudo rm -rf [maven的路径] 二 安装maven 1.下载maven压缩包 mac下 ...