登录、django操作redis
这些接口没有登录的,首先要执行pip install django_redis,显示django-redis-4.11.0安装成功,但是存在from django_redis标红的情况,这是因为装到了python3.5里,项目是在python3.7中,所有要到python3.7的scripts目录下执行pip install django_redis就可以了,还要执行pip install itsdangerous,首先要配置redis,在settings.py里复制下面的代码:
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://118.24.3.40:6379/0", # 第0个数据库
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100},
"PASSWORD": "HK139bc&*", # 密码
}
},
"redis2": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100, 'decode_responses': True},
"PASSWORD": "123456", # 密码
}
}
} # redis配置
然后在model_test.py(保证有那三行代码)里写段代码:
from django_redis import get_redis_connection
r = get_redis_connection() # 指定连接哪个redis,如果没有指定默认是default
r.get()
r.set()
原理是登录成功后生成一个token,存到redis里,然后再返回给客户端一个token,进行其他操作时拿着这个token去请求redis,第一关要进行loads一下,如果没匹配上,证明token不对或失效,如果这关过了再去redis找,如果找到就可以进行其他操作,退出的时候就在redis里把这个token删除就可以了,token有两个功能,第一个功能是保持会话,第二个功能是代表用户信息的,知道token就知道用户是谁
如果没有itsdangerous.TimedJSONWebSignatureSerializer,要去以前的版本里拷一下itsdangerous.py文件,放到D:\my_python\Lib\site-packages的路径下,保证程序正常运行
如果过期时间比较短的话会报Signature expired
在models.py里创建一个user表,新增代码如下图:
makemigrations,生成表结构,migrate在数据库里生成User表,然后在admin.py里新增两行代码,如下图:
然后访问http://127.0.0.1:8000/admin/,输入用户名admin,密码sun123456!,登录成功后可以看到Users表,如下图:
然后新增两条数据,创建成功后在user表里可以看到,如下图:
在testcase目录下创建一个文件,utils.py,再创建一个文件,const.py,const.py中的代码是token_expire = 60 * 60 * 1,utils.py里的代码如下:
from django_redis import get_redis_connection
import itsdangerous
from django.conf import settings
from .const import token_expire
class Token:
t = itsdangerous.TimedJSONWebSignatureSerializer(settings.SECRET_KEY, expires_in=token_expire)
@classmethod
def create_token(cls, data):
token = cls.t.dumps(data).decode()
return token
@classmethod
def check_token(cls, token):
try:
data = cls.t.loads(token)
except:
return False
return data
写完这两个函数后接下来写登录逻辑,在testcase目录下的forms.py文件里写UserForm这个类,要导入from django.core.exceptions import ValidationError、from utils.tools import FormatFormError(UserForm继承FormatFormError这个类,在view3.py的else里的form才可以点出来),新增代码如下图:
然后在testcase目录下的view3.py文件里写LoginView这个类,在写的过程中要导入from django.views import View、from utils.custom_response import nb_response、from .forms import ProjectForm, CaseForm, UserForm,再导入from django_redis import get_redis_connection、from .utils import Token,在const.py里新增session_prefix = 'session:'一行代码,然后在view3.py下再导入from .const import token_expire, session_prefix,新增代码如下图:
接下来配置url,在testcase目录下的urls.py里增加path('login', view3.LoginView.as_view()),然后在浏览器里输入http://127.0.0.1:8000/testcase/login,报如下错误:
在浏览器里输入http://127.0.0.1:8000/testcase/login?username=xiaohua&password=123456,点击回车,可以看到生成了token,如下图:
然后去redis里看一下token,如下图:
OK了,接下来要在中间件里实现其他接口,在utils目录下middle_ware.py文件里PutMiddleware类下,process_request方法下输入print(dir(request)),然后在postman里配置如下:
点击Send按钮可以看到好多方法,有POST、GET、META等,然后process_request方法下输入print(request.META),pycharm里配置如下图:
postman配置如下图:
点击Send按钮在日志里可以看到如下图:
然后修改一下Headers里的key和value为token和XXX,在请求一下在日志看到如下图:
从上面两图可以看出一个规律,就是以key请求的时候在日志里自动加上了HTTP_,并把key变为大写
在middle_ware.py文件里再写一个类TokenMiddleware,token要分两次校验,第一次通过itsdangerous校验,如果第一次就没有通过校验就不用redis来校验了,首先要导入from testcase.utils import Token,新增代码如下图:
然后配置settings.py,在MIDDLEWARE里输入utils.middle_ware.TokenMiddleware,接下来在浏览器里输入http://127.0.0.1:8000/testcase/case,点击回车:
如上图,查询用例没有传token报请登录!,于是在浏览器里输入http://127.0.0.1:8000/testcase/case?token=实际写到redis里的token,点击回车,可以看到12条用例,从上图的代码看没有解析出来就报错,如果解析出来了就要从redis里取,接下来继续输入代码,要导入from django_redis import get_redis_connection和from testcase.const import session_prefix,新增代码如下图:
但是在浏览器里输入http://127.0.0.1:8000/testcase/login?username=xiaohua&password=123456,点击回车,报如下图:
正常登录也报请登录,看代码哪里有问题,应该是url没有校验,因此要设计一个白名单,如果url出现在白名单里就不进行校验,如果没有出现在白名单里就校验,在utils目录下的const.py文件里配置white_list = ['register', 'login'],在middle_ware.py文件里导入from .const import white_list,然后进行循环判断,如下图:
如果路径出现在白名单里,return函数就结束了,没有出现就往下走,在user目录下创建一个forms.py文件,新增代码如下图:
在user目录下创建一个views_new.py文件,新增代码如下图:
然后配一下url,在my_love目录下的urls.py文件里配置一下,导入from user import views_new,然后添加path('article', views_new.ArticleView.as_view()),,然后访问http://127.0.0.1:8000/article,点击回车,弹出如下图:
然后注释settings.py文件里的MIDDLEWARE里'utils.middle_ware.TokenMiddleware',这行,然后去utils目录下找到middle_ware.py文件,导入import traceback,在PutMiddleware类下process_exception方法里加上一行代码,如下图:
在访问一下,报如下错误:
在日志里可以看到TypeError: <ImageFieldFile: images/1.jpg> is not JSON serializable,然后去utils目录下,找到custom_response.py文件,新增如下图:
在访问一下,在日志里看到,如下图:
这个不是字符串,所以报错了,去utils目录下找到tools.py文件,在model_to_dict方法里,新增如下代码:
在访问http://127.0.0.1:8000/article,点击回车,查询出91篇文章,可以看到image是hello,就是代码里赋的值,日志里看到path方法,就是路径,如下图:
因此需要修改代码,将print('ImageFieldFile', dir(value))和value='hello'去掉,输入value=value.path,在访问,可以看到image的值是一个绝对路径,同时访问成功的时候页面显示category是一个整数,如果返回的字段不是想要的结果,表里没有,是通过运算得出来的,要重写utils目录下的custom_view.py文件里的BaseView类下面的get_paginator方法,接下来修改代码,get_paginator里的代码更改如下图:
把get_paginator方法里剩余的代码拷到GetView类里,修改后GetView类里的get方法如下图:
接下来在user目录下的views_new.py文件里重写get方法,把GetView类里的代码拷贝到views_new.py文件里,修改后的代码如下图:
访问http://127.0.0.1:8000/article,点击回车,可以看到91条数据,每个小字典里有10个字段,如下图:
然后增加字段,category是外键,通过.就可以把category表里的字段取出来,新增代码如下图:
刷新页面就会看到category_name这个字段,如下图:
还可以修改字段,先添加category_id字段,再删除category字段,代码如下图:
再次刷新页面,看到如下图:
可以看到添加成功的字段category_name和category_id