views.py
re
from rest_framework.views APIView
from rest_framework.response Response
from .utils get_user_obj
......
CheckPhoneNumber(APIView):
def get(self,request):
phone_number = request.GET.get(phone)
验证手机号格式
if not re.match(^1[3-9][0-9]{9}$',phone_number): 格式不对
return Response({error_msg':手机号格式有误,请重新输入!'},status=status.HTTP_400_BAD_REQUEST)
验证手机号唯一性
ret = get_user_obj(phone_number)
if ret:
': 手机号已被注册,请换手机号status.HTTP_400_BAD_REQUEST)
msgok'})
-->
="register_btn"="registerHandler">注册 methods:{
......
registerHandler(){
this.$axios.post(`${this.$settings.Host}/`,{
将输入框的四项一并提交到后台
sms:.sms,mobile:.mobile,password:.r_password,}).then((res)=>{
}).{
})
},
register/ views.py
RegisterView(CreateAPIView):
queryset = models.User.objects.all()
serializer_class = RegisterModelSerializer
serializers.py
RegisterModelSerializer(serializers.ModelSerializer):
'''
sms,r_password这两个字段只需要write_only=True
意思是:反序列化校验的时候,这两个字段必须要传递给我
但是序列化返回数据的时候,这两个字段是不序列化出来的
id,token这两个字段只需要read_only=True
意思是:反序列化校验的时候,这些字段是无需校验的
但是序列化返回数据的时候,必须要返回这两个数据
'''
id = serializers.IntegerField(read_only=True)
sms和r_password这两个字段数据库并没有,但是反序列化的时候还需要校验这两个字段,所以需要在这写这两个字段
将两个字段设置为write_only=True的原因是因为:验证码和确认密码这两个字段只做反序列化校验功能,不需要序列化返回到前端
sms = serializers.CharField(max_length=6,min_length=4,write_only=True) '3333'
r_password = serializers.CharField(write_only=True)
token = serializers.CharField(read_only=True) 后端需要给前端传递token
Meta:
model = models.User
fields = [idpasswordr_passwordsmstoken]
extra_kwargs = {
': {write_only: True},}
校验密码和确认密码
validate(self,attrs):
校验手机号
phone_number = attrs.get( 后端校验手机号格式是否正确
raise serializers.ValidationError(手机号格式不对)
验证手机号是否已经存在
ret =手机号已经存在!!)
p1 = attrs.get()
p2 = attrs.get( 验证密码和确认密码是否一致
if p1 != p2:
两次密码不一致,请核对)
todo 校验验证码[待做]
attrs
重写create方法:因为序列化器中有的字段是不需要反序列化存到数据库中
'''
create(self,validated_data):
确认密码和验证码不需要存到数据库中,所以要剔除它们
validated_data.pop()
validated_data.pop( 密码加密
hash_password = make_password(validated_data[])
validated_data['] = hash_password
以上处理好的数据存到数据库中
user = models.User.objects.create(
**validated_data
)
user.token = 123' 硬加上一个token
return user 返回user对象时,就会有token这个属性了
dev.py
设置redis缓存
CACHES = {
默认缓存
"default": {
BACKEND": django_redis.cache.RedisCache 项目上线时,需要调整这里的路径
LOCATIONredis://127.0.0.1:6379/0OPTIONS: {
CLIENT_CLASSdjango_redis.client.DefaultClient 提供给xadmin或者admin的session存储
sessionredis://127.0.0.1:6379/1 提供存储短信验证码
sms_code:{
redis://127.0.0.1:6379/2 设置xadmin用户登录时,登录信息session保存到redis
SESSION_ENGINE = django.contrib.sessions.backends.cache
SESSION_CACHE_ALIAS = "
="width: 34%;height: 41px;"="getSmsCode">点击获取验证码 getSmsCode(){
this.$settings.Host}/`)
}
views
path
urlpatterns =sms_code/(?P<phone>^1[3-9][0-9]{9}$)/users/views.py
from django_redis get_redis_connection
GetSMSCodeView(APIView):
验证是否已经发送过短信了
conn = get_redis_connection()
ret = conn.get(mobile_interval_%s'%phone)
60秒内已经发送过了,别瞎搞 生成验证码
sms_code = %06d" % random.randint(0,999999)
保存验证码
验证码是存到redis里的,因为验证码有时限,所以用setex将验证码存入
存入方式是以键值对存入的:
key:手机号 value:验证码
conn.setex(mobile_%s'%phone,sms_code,contains.SMS_CODE_EXPIRE_TIME) 设置有效期
#
conn.setex( 设置发送短信的时间间隔
todo 发送验证码
'})
两个常量放到constant.py中
settings/constant.py
settings/constant.py
SMS_CODE_EXPIRE_TIME = 60*10 有效时间
SMS_CODE_INTERVAL_TIME = 60 间隔时间
4.解决登录不上Xadmin的bug
登录不上Xadmin的原因是:
之前我们设置了Xadmin使用咱们自己创建的用户表,而不是使用Xadmin原先自带的表:传送门:Xadmin使用自己创建的用户表
而在昨天我们又重写了jwt代码,让其除了验证用户名和密码还要验证ticket票据:传送门:重写jwt代码来实现对滑动成功的认证
这样的话就会导致我们在登录Xadmin的时候,也会验证ticket票据,所以会登录失败。
所以我们做一个if判断:
当ticket有值的时候才走滑动成功的认证:验证用户名 密码 ticket randstr
当ticket没有值的时候,就做常规认证,只验证用户名和密码即可
users/utils.py
users/utils.py
CustomeModelBackend(ModelBackend):
def authenticate(self,username=None,password=None,**kwargs):
try:
user_obj = get_user_obj(username)
看是否有票据信息,如果没有,直接走下面的代码(Xadmin用户名密码登录)
如果有票据信息,走if里面的代码 对票据进行验证
这样的话xadmin就不会因为走票据信息这套逻辑导致登录失败了
'''
if kwargs.get(ticket):
ticket = kwargs.get()
userip = request.META[REMOTE_ADDR]
randstr = kwargs.get(randstr)
print(userip: {
aid": settings.FSQ.get(appid),1)">AppSecretKeyapp_serect_keyTicket: ticket,1)">Randstr: randstr,1)">UserIP: userip
}
params = urlencode(params).encode()
url = settings.FSQ.get(URL)
f = urlopen(url,params)
content = f.read()
res = json.loads(content)
print(res) {'response': '1','evil_level': '0','err_msg': 'OK'}
if res.get(response') != 1:
None
user_obj:
user_obj.check_password(password):
user_obj
else:
None
except Exception:
logger.error(验证过程代码有误,请联系管理员)
return None
5.redis
1.redis简要介绍
mysql的表类型[表引擎,存储引擎],memory 表结构和表数据分开存储的,表结构保存在硬盘中,表数据保存在内存中.
memcache 一款软件,可以使用键值对的格式,保存数据到内存中.
redis是意大利的工程师开发的开源免费的高速内存缓存数据库.需要注意的是,作者本身是只开发了linux版本的redis数据库.
?
window系统的redis是微软团队根据官方的linux版本高仿的
官方原版: https://redis.io/
中文官网:http://www.redis.cn
参考命令:http://doc.redisfans.com/
2.redis的下载和安装
下载地址: https://github.com/MicrosoftArchive/redis/releases
使用以下命令启动redis服务端[配置文件路径根据自己的摆放位置改动]
redis-server C:/tool/redis/redis.windows.conf
redis作为windows服务启动方式
redis-server --service-install redis.windows.conf
启动服务:redis-server --service-start
停止服务:redis-server --service-stop
3.redis的使用
Redis 是一个高性能的key-value数据格式的内存缓存,NoSQL数据库。
NOSQL:not only sql,泛指非关系型数据库。
关系型数据库: (mysql,oracle,sql server,sqlite,db2)
1. 数据存放在表中,表之间有关系。
2. 通用的SQL操作语言。
3. 大部分支持事务。
非关系型数据库:[ redis,hadoop,mangoDB]:
1. 没有数据表的概念,不同的nosql数据库存放数据位置不同。
2. nosql数据库没有通用的操作语言。
3. 基本不支持事务。 redis支持简单事务
redis:内存型(数据存放在内存中)的非关系型(nosql)key-value(键值存储)数据库,支持数据的持久化(注: 数据持久化时将数据存放到文件中,每次启动redis之后会先将文件中数据加载到内存),经常用来做缓存(用来缓存一些经常用到的数据,提高读写速度)。
redis是一款基于CS架构的数据库,所以redis有客户端,也有服务端。
其中,客户端可以使用python等编程语言,也可以终端命令行工具
?
redis客户端连接服务器:
redis-cli -h `redis服务器ip` -p `redis服务器port` 6379
4.redis数据类型
1. string类型:
字符串类型是 Redis 中最为基础的数据存储类型,它在 Redis 中是二进制安全的,也就是byte类型
最大容量是512M。
key: string
2. hash类型:
hash用于存储对象,对象的结构为属性、值,值的类型为string。
key:{
域:值[这里的值只能是字符串],
域:值,
域:值,
域:值,
...
}
3. list类型:
列表的元素类型为string。
key:[ 值1,值2,值3..... ]
4. set类型:
无序集合,元素为string类型,元素唯一不重复,没有修改操作。
key: {值1,值4,值3,值5,....}
5. zset类型[sortset]:
有序集合,元素为string类型,元素唯一不重复,有修改操作。
key:{
值: 权重值,值: 权重值,}
5.String
如果设置的键不存在则为添加,如果设置的键已经存在则修改
-
设置键值
set key value
-
例1:设置键为name
值为xiaoming
的数据
set name xiaoming
-
设置键值及过期时间,以秒为单位
setex key seconds value
-
例2:设置键为aa
值为aa
过期时间为3秒的数据
setex name 20 xiaoming
?
关于设置保存数据的有效期
setex 添加保存数据到redis,同时设置有效期
格式:
setex key time value
expire 给已有的数据重新设置有效期
格式:
expire key time
-
追加值
append key value
-
例4:向键为a1
中追加值haha
,a1='xx'
append a1 haha
a1= 'xxhaha'
?
-
获取:根据键获取值,如果不存在此键则返回nil
get key
-
例5:获取键name
的值
get name
?
-
根据多个键获取多个值
mget key1 key2 ...
-
例6:获取键a1、a2、a3
的值
mget a1 a2 a3
6.键操作
-
查找键,参数?持正则表达式
keys pattern
-
例1:查看所有键
keys *
-
例2:查看名称中包含a
的键
keys a*
?
-
判断键是否存在,如果存在返回1
,不存在返回0
exists key1
-
例3:判断键a1
是否存在
exists a1
?
-
删除键及对应的值
del key1 key2 ...
-
例5:删除键a2、a3
del a2 a3
-
查看有效时间,以秒为单位
ttl key
-
例7:查看键bb
的有效时间
ttl bb
7.hash
结构:
键key:{
域field:值value
}
-
获取所有属性的值
hvals key
-
例6:获取键u2
所有属性的值
hvals u2
-
删除属性,属性对应的值会被?起删除
hdel key field1 field2 ...
-
例7:删除键u2
的属性age
hdel u2 age
8.set
可删除不可修改
?
-
返回所有的元素
smembers key
-
例2:获取键a3
的集合中所有元素
smembers a3
?
-
删除指定元素
srem key value
-
例3:删除键a3
的集合中元素wangwu
srem a3 wangwu
9.list
列表的元素类型为string
按照插?顺序排序
?
设置指定索引位置的元素值
?
lrem key count value
-
例6.2:从a2
列表右侧开始删除2个b
lrem a2 -2 b
-
例6.3:查看列表a2
的所有元素
lrange a2 0 -1
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!