form校验参数
在views.py里先把CaseForm类写出来,前提是导入forms,from django import forms,如下图:
然后修改CaseView类下的post方法,如下图:
要把校验字段的逻辑放在CaseForm里,如果校验单个字段,要以clean开头,加上字段的名字,如果校验多个字段单独clean,前提要导入from django.core.exceptions import ValidationError,方法新增代码如下图:
上图中clean_method是钩子,就是写类的时候预留出来的,然后把正常和异常的请求都试一下,如果发生异常,可以在pycharm日志看到异常的原因
ModelForm的使用
接下来使用ModelForm,这个更好用,CaseForm里的字段和方法都是手写的,使用ModelForm那些字段和方法都不需要写,代码更加简洁,在CaseForm类下面在创建一个CaseForm2的类,新增代码如下图:
然后把CaseView类里的CaseForm改成CaseForm2,如下图:
在postman里点击Send按钮,如下图:
报错了,日志里报run_count是必填项,在run_count增加null=True, blank=True,这样run_count就不是非必填的了,可以为空了,接下来修改表结构,运行python manage.py makemigrations和python manage.py migrate,再次在postman里点击Send按钮,报错了,报错如下图:
修改代码,把CaseForm2类下面的fields字段注释,写上如下图代码:
再次在postman里点击Send按钮,这次成功了,可以多次添加重复的标题,因为标题没有设置唯一性,如果在title里设置unique=True,那么添加重复的title就会报错,然后更改表结构,报如下的错误:
报这个错误的原因是表里有重复的标题,改一下标题,使其不重复,再更改表结构就不报错了,接下来用postman继续添加相同title的用例,在日志里报{'title': [ValidationError(['具有 用例标题 的 用例表 已存在。'])]}这样的错误,可以看出使用ModelForm更简单,也不用判断了,只需要指定一下表,排除哪些字段就ok了
接下来在views.py里的CaseSet类上面再创建一个CaseSetForm的类,新增代码如下图:
接下来修改CaseSet里面的代码,如下图:
然后在urls.py里找到路径是path('case_set_new', views.CaseSet.as_view()),接下来在postman里请求,如下图:
请求成功了也可以把models.CaseSet.objects.create(**form.cleaned_data)这行代码注释掉,换成form.save(),同样可以达到效果,如果只传一个参数请求,请求失败会在日志里看到相关的信息,前提是在else下、data上加上print(form.errors.as_data())这行代码
把所有代码都写在views.py里有点乱,在testcase目录下新建一个forms.py文件,专门写Form,先把CaseSetForm和CaseForm这两个类写出来,然后把views.py里的CaseForm类拷过来,改个名字叫CaseFormOld,forms.py里新增代码如下图:
然后在testcase目录下新建一个views_new.py文件,专门写逻辑,把views.py文件里的CaseView和CaseSet类的代码拷到views_new.py里,根据标红在导入相关的文件,views_new.py文件里的代码如下图:
然后在配置urls.py文件,新增代码如下图:
报错都是报参数错误,只有print才能看到,前端不友好,如果能把哪个错误打印出来就更友好了,于是在CaseSet类里else的代码下写上print(dir(form.errors)),在用postman请求就会发现好多错误的方法,其中有个get_json_data(),然后在print(dir(form.errors))下面在加上一行print(form.errors.get_json_data()),在请求如果只传name就会打印出来:{'describe': [{'message': '这个字段是必填项。', 'code': 'required'}]},如果两个都不传,打印出{'name': [{'message': '这个字段是必填项。', 'code': 'required'}], 'describe': [{'message': '这个字段是必填项。', 'code': 'required'}]},这是一个字典只要拿到key就可以把value打印出来,value是一个list,循环这个list,就会拿到里面第一个字典message的错误信息
因为views_new.py里每个else都会返回异常的信息,因此要建一个公共的类,在一级目录下新建一个utils目录,在utils下新建一个tools.py文件,把格式化错误信息的代码放到这个文件里,新增代码如下图:
然后在forms.py文件里导入from utils.tools import FormatFormError,CaseSetForm和CaseForm都要继承FormatFormError类,因此修改后forms.py文件里的代码如下图:
因此在实例化CaseSetForm和CaseForm不仅要继承ModelForm,还要继承FormatFormError类,修改后views_new.py文件里的代码如下图:
在运行postman的时候可以看到具体的错误信息,如下图:
接下来把分页先实现了,在views_new.py文件里导入from django.core.paginator import Paginator,因为要在查询的时候进行分页,所以要在个get方法里面进行,定义两个变量limit和page,传过来就按照传过来的实现,没传都有默认值,新增代码如下图:
再定义个search变量,按照什么进行模糊查询,要导入from django.db.models import Q,title、describe、url、params只要任一个包含search,走if,如果没传search,走else,else就是全部查出来,新增代码如下图:
在浏览器里访问http://127.0.0.1:8000/testcase/case?page=3&search=case,点击回车,查询结果如下图:
模糊查询实现了,在实现精确查询,精确查询优先级高于模糊查询,新增代码如下图:
根据id查询如下图:
根据title查询如下图:
根据method查询如下图:
分页、模糊查询、精确查询都实现了,但是都在一个get方法里,不太好,把每个功能都写成一个函数,让get里的代码更简介,前提是要导入from django.db.models import Q,CaseView类中的代码如下图:
接下来补全views_new.py里的CaseSet类中的get方法,更简洁的代码新增如下图:
第一次循环name__contains=search和q取并集,q是('name__contains', 'test'),第二次循环describe__contains=search和q取并集,q是('name__contains', 'test'),('describe__contains', 'test')
print('q', q)在日志里打印出
4种情况都试一下,可以查询成功
还有个问题是查询出的记录里没有出现create_time和update_time以及is_delete不应该显示出来,因为model_to_dict的问题,因为这些字段是不可编辑的,由于源码里有下面的代码,不可编辑直接就continue了,所以用postman查询数据的时候看不到create_time和update_time
if not getattr(f, 'editable', False):
continue