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 ...
随机推荐
- Alpha项目测试--个人第五次作业
img {border:solid 1px black} 这个作业属于哪个课程 <https://edu.cnblogs.com/campus/xnsy/2019autumnsystemanal ...
- [唐胡璐]Selenium技巧- Prop.Properties配置测试应用的环境和其他配置项
prop.propertiesfile contains important info that needs to be changed before the test is run, such a ...
- .NET界面开发新体验!DevExpress v19.2.4全新来袭
DevExpress Universal Subscription(又名DevExpress宇宙版或DXperience Universal Suite)是全球使用广泛的.NET用户界面控件套包,De ...
- airflow--Error: Already running on PID 22603 (or pid file '/home/rdev/airflow/airflow-webserver.pid' is stale)
kill这个残留进程然后直接重新启动airflow webserver就OK (wqbin) rdev@testhk1:~/etl/py_etl/warehouse$ cat /home/rdev/a ...
- python 赋值魔法
序列解包: >>> x,y,z = 1, 2, 3>>> print(x, y, z)1 2 3 >>> a,b, *reset = [1,2,3 ...
- 51nod 1412
考虑到只与深度和点的个数有关$f[n][d]$ 表示 $n$ 个点,深度为 $d$ 的 $AVL$ 树有多少种 枚举左子树大小为 $i$, 进行转移并且深度为 $logn$ 级别 $f[n][d] = ...
- 文件描述符、文件表项、V节点表项的一些总结
转自 http://blog.csdn.net/gzzheyi/article/details/7739556 表格可以参见APUE 第三版 P61. 文件描述符(进程级别): 1).在每个进程表中 ...
- 常用exporter下载
1.node_exporter https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter- ...
- javascript中稀疏数组和密集数组
密集数组 数组是一片连续的存储空间,有着固定的长度.加入数组其实位置是address,长度为n,那么占用的存储空间是address[0],address[1],address[2].......add ...
- JAVA基础知识|TCP/IP协议
虽然写代码也有一定的年头了,但是对于一些基础概念,还是很模糊.这在后来的学习过程中,带来了很大的痛苦,所以痛定思痛,决心重新学习这些概念.并把自己的理解和查询的资料做一些整合,便于以后查阅! 一.什么 ...