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 ...
随机推荐
- 注册表操作 Microsoft.Win32.Registry与RegistryKey类
一.注册表操作简介 Registry 类,RegistryKey 类提供了操作注册表的接口 RegistryValueKind:用于指定操作注册表的数据类型 一.注册表巢 在注册表中,最上面的节点是注 ...
- Python进阶:都说好用的 Python 命令行库click
click 是一个以尽可能少的代码.以组合的方式创建优美的命令行程序的 Python 包.它有很高的可配置性,同时也能开箱即用. 它旨在让编写命令行工具的过程既快速又有趣,还能防止由于无法实现预期的 ...
- 2019EC-Final参赛总结
本来想发知乎上的,后来发现太长就放这好了23333 没写过这种东西,所以写得比较混乱&流水账 以下内容均为我的个人视角XD 赛前 在车上的时候,红太阳跟我们说他头晕(虽然他好像每场比赛都头 ...
- process 请求数据解析问题
开发过程中发现ajax提交的数据无法被express正确的解析,主要的情况是这样的: // 浏览器端post一个对象 $.ajax({ url:"/save", type:&quo ...
- Appium自动化测试教程-自学网-SDK
SDK:软件开发工具包,被软件开发工程师用于特定的软件包.软件框架.硬件平台.操作系统等建立应用软件的开发工具的集合. 因此,Android SDK指的是Android专属的软件开发工具包. 1,安装 ...
- php注意事项|要点
1. 用单引号代替双引号来包含字符串,这样做会更快一些.因为 PHP 会在双引号包围的 字符串中搜寻变量,单引号则不会,注意:只有 echo 能这么做,它是一种可以把多个字符 串当作参数的“函数”(译 ...
- 经过测试,feign只能通过@RequestBody传对象参数
通过feign调用,使用ModelAttribute 注解,参数没法传到对应的server
- windows游戏编程地址
本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/22309325 作者:jadeshu 邮箱: jades ...
- Java 方法的重写
方法重写规则: 1.子类要重写的方法与父类方法具有完全相同的返回类型+方法名称+参数列表: 2.子类要重写的方法的访问权限大于或者等于父类方法的访问权限: 3.子类要重写的方法不能抛出比父类方法更大的 ...
- c++ 排序,<< 运算符重载
#include <iostream> #include <functional> #include <list> using namespace std; ost ...