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 ...
随机推荐
- 3.使用webpack配置文件webpack.confg.js配置打包文件的入口和出口
在项目根目录下新建webpack.config.js文件 webpack.config.js文件配置如下: // Node的路径操作使用的是path模块 const path=require('pat ...
- phpstudy如何配置域名
其他选项菜单=>站点域名管理=>站点管理填入信息后点击“新增”按钮=>点击“保存设置并生成配置文件”按钮=>打开hosts=>127.0.0.1 www.gohosts. ...
- WCF Windows基础通信
概述 WCF,Windows Communication Foundation ,Windows通信基础, 面向服务的架构,Service Orientation Architechture=SOP ...
- 5、Spring Boot 2.x 启动原理解析
1.5 Spring Boot 启动原理解析 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏 ...
- git commit 详解
git commit 命令用来将本地暂存的修改提交到版本库. git commit -m '提交信息'. 我们用的比较多的应该就是-m 参数.添加提交信息. 经常手抖的同学可能会知道,git comm ...
- CAZAC序列
定义: CAZAC(Const Amplitude Zero Auto-Corelation),即为恒包络零自相关序列. 性质: 1,恒包络特性:任意长度的CAZAC序列幅值恒定. 2,理想的周期自相 ...
- 查看文件被哪个进程lock住
How do you know who or what is locking a remote file? http://serverfault.com/questions/1948/how-do-y ...
- @Async 异步注释 @EnableAsync
@SpringBootApplication @ComponentScan(basePackages = "com.fddsfsg") //@EnableSwagger2 @Ena ...
- CTS2019自闭记
没想到吧,我竟然还有一篇游记. Day 0 上午开开心心地考完了中考英语听说考试,然后就出发去机场了. 第一次一个人坐飞机还有点小激动? 7点左右到的北京,到酒店就已经9点了,赶紧跟着hz学长学了一下 ...
- 线段树(结构体建法_QAQ)
线段树(结构体)模板 #include<iostream> #include<cstdio> #include<queue> #include<cstring ...