django form --day15
一、cvb,fvb
CVB class view
1 from django.views import View 2 class Articl_View(View): 3 4 def get(self,request): 5 print('get请求。。。') 6 categories = Category.objects.all() # 返回所有的分类 7 return render(request, 'form.html', locals()) # 8 9 def post(self,request): 10 print('post请求。。。') 11 title = request.POST.get('title') 12 desc = request.POST.get('desc') 13 category = request.POST.get('category') 14 content = request.POST.get('content') 15 article = Article(title=title, desc=desc, category_id=category) 16 article.save() 17 # return render(request,'index.html') 18 return HttpResponseRedirect('/index') # 重定向
FVB 函数view
1 def add_article(request): 2 if request.method == 'GET':#第一次请求接口,是get请求 3 categories =Category.objects.all()#返回所有的分类 4 return render(request,'form.html',locals())# 5 else: 6 title = request.POST.get('title') 7 desc = request.POST.get('desc') 8 category = request.POST.get('category') 9 content = request.POST.get('content') 10 article = Article(title=title,desc=desc,category_id=category) 11 article.save() 12 # return render(request,'index.html') 13 return HttpResponseRedirect('/index')#重定向
form表单方式和js中的axoius的区别
1、form表单提交后页面会刷新
2、js不会刷新页面
CSRF token验证失败,请求被中断问题:
1、CSRF为了防止重复提交
2、每次请求
客户端访问了get请求,服务端返回页面,但是页面会带一个字符串,然后添加功能后请求post 但是客户端没有带入字符串的请求,就会报错403
django默认post请求都需要加入CSRF token
解决办法:
1、settings.py文件中将以下注释内容注释,但是没有解决重复提交的问题
1 MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware', 3 'django.contrib.sessions.middleware.SessionMiddleware', 4 'django.middleware.common.CommonMiddleware', 5 # 'django.middleware.csrf.CsrfViewMiddleware', 6 'django.contrib.auth.middleware.AuthenticationMiddleware', 7 'django.contrib.messages.middleware.MessageMiddleware', 8 'django.middleware.clickjacking.XFrameOptionsMiddleware', 9 ]
2、form.html中 如果用form表单需要增加 {% csrf_token %}
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>添加文章入口</title> 6 </head> 7 <body> 8 <form action="/add_article/" method="post"> 9 {% csrf_token %} 10 title:<input name="title" type="text"> 11 desc:<input name="desc" > 12 content:<input name="content"> 13 <select name = "category"> 14 {% for a in categories %} 15 <option value = "{{ a.id }}">{{ a.name }}</option> 16 {% endfor %} 17 </select> 18 <input type="submit" value="提交"> 19 </form> 20 </body></html>
问题:参数需要校验
导入库
1 from django import forms 2 from django.core.exceptions import ValidationError
方式一、使用Form校验 views.py文件中实现
1 class CaseForm(forms.Form): 2 '''校验请求参数''' 3 title = forms.CharField(max_length=50,min_length=2) 4 desc = forms.CharField(max_length=60,required=False) 5 method = forms.IntegerField() # 0 1 2 3 6 url = forms.URLField() 7 params = forms.CharField(max_length=100) 8 9 def clean_method(self): #钩子函数,校验method参数 10 method = self.cleaned_data.get('method') 11 if method not in (0,1,2,3): 12 raise ValidationError('method值不对') 13 return method 14 15 def clean_title(self):#校验单个字段 16 title = self.cleaned_data.get('title') 17 if models.Case.objects.filter(title=title).count()>0: 18 raise ValidationError('用例标题已经存在') 19 return title 20 21 def clean(self):#校验多个字段 22 title = self.cleaned_data.get('title') 23 method = self.cleaned_data.get('method')
方式二、和数据录相关继承(forms.ModelForm)views.py文件中实现
1 class CaseSetForm(forms.ModelForm):#集合校验数据 2 class Meta: 3 model = models.CaseSet 4 fields = '__all__'#全部校验 5 exclude = ['is_delete']#排除不校验参数
方式三、单独新创建forms.py的文件,只写form校验内容
1 from django import forms 2 from django.core.exceptions import ValidationError 3 4 from . import models 5 6 7 class CaseSetForm(forms.ModelForm):#集合校验数据 8 class Meta: 9 model = models.CaseSet 10 fields = '__all__'#全部校验 11 exclude = ['is_delete']#排除不校验参数
views.py中实现
1 from . import models 2 from . import forms 3 from django.views import View 4 5 class CaseView(View): 6 def post(self,request): 7 form = forms.CaseForm(request.POST)#这里具体引用 8 if form.is_valid(): 9 models.Case.objects.create(**form.cleaned_data) 10 data = {'code': 0, 'msg': '添加成功'} 11 else: 12 data = {'code':-1,'msg':form.error_msg}#显示具体的错误信息 13 return JsonResponse(data)
二、前后端分离实现方式实例
整体思路如图:
1、新创建应用
1.1新创建的应用--testcase
pycharm编辑器--Tools--Run manage.py Task...
输入:startapp +应用名称
1.2 dj_test 目录下settings.py增加应该名称
2、testcase目录下创建数据库models.py
1 from django.db import models 2 3 # Create your models here. 4 # 公共的字段,然后子类继承父类中的公共方法,问题:创建的表的时候会创建,所以增加【Class Meta】 5 class BaseModel(models.Model): 6 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') 7 update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') 8 is_delete = models.BooleanField(verbose_name='是否删除', default=False) 9 class Meta: 10 abstract = True #声明这个类只是用来继承的,不会创建这张表 11 #子类 12 class CaseSet(BaseModel): 13 name = models.CharField(verbose_name='集合名称',max_length=60) 14 desc = models.CharField(verbose_name='集合描述',max_length=70) 15 16 17 def __str__(self): 18 return self.name 19 20 class Meta: 21 db_table = 'case_set' 22 verbose_name ='用例集合表' 23 verbose_name_plural = verbose_name 24 25 26 class Case(BaseModel): 27 title = models.CharField(verbose_name='用例标题',max_length=80,db_index=True,unique=True) 28 desc = models.CharField(verbose_name='用例描述',max_length=120) 29 method_choice = [ 30 [0,'get'], 31 [1,'post'], 32 [2,'put'], 33 [3,'delete'], 34 ] 35 method = models.SmallIntegerField(choices=method_choice,verbose_name='请求方式',default=0) 36 url = models.URLField(max_length=50,verbose_name='请求url') 37 params = models.TextField(verbose_name='请求参数') 38 run_count = models.IntegerField(verbose_name='运行次数',default=0,null=True,blank=True) 39 run_time = models.DateTimeField(verbose_name='运行时间',null=True,blank=True) 40 case_set = models.ManyToManyField(CaseSet,db_constraint=False,verbose_name='用例集合',null=True,blank=True)#用例和用例集合之间建立连接,多对多 41 42 43 def __str__(self): 44 return self.title 45 46 class Meta: 47 db_table = 'case' 48 verbose_name ='用例表' 49 verbose_name_plural = verbose_name
2.1 生成数据库
pycharm编辑器--Tools--Run manage.py Task...
2.2 同步数据库
migrate
3、testcase目录下views.py编辑接口实现
3.1 普通实现方式--不建议
添加集合:
1 def case_set(request): 2 # 添加用例集合 3 name = request.POST.get('name') 4 desc = request.POST.get('desc') 5 if name.strip() and desc.strip(): 6 models.CaseSet.objects.create(name=name, desc=desc) 7 data = {'code': 0, 'msg': '添加成功'} 8 else: 9 data = {'code': -1, 'msg': '参数错误'} 10 return JsonResponse(data)
查看集合:
1 def case_set_all(req): 2 #查看用例 3 case_sets = models.CaseSet.objects.filter(is_delete=False) 4 5 data = []#定义 6 for c in case_sets: 7 d = model_to_dict(c)#实现把数据转成字典 8 data.append(d)#将字典添加到list中 9 response = {'code': 0, 'msg': '成功', 'data': data} 10 11 return JsonResponse(response, json_dumps_params={'ensure_ascii': False}) # {'code': 0, 'msg': '成功',data:[ ]},json_dumps_paramsjson_dumps_params显示中文
3.2resultful方式
def case_set_new(req):#restful的风格,开发接口的规范 if req.method == 'GET': case_sets = models.CaseSet.objects.filter(is_delete=False) data = [] for c in case_sets: d = model_to_dict(c) data.append(d) response = {'code': 0, 'msg': '成功', 'data': data} return JsonResponse(response, json_dumps_params={'ensure_ascii': False}) # {'code': 0, 'msg': '成功',data:[ ]} elif req.method == 'POST': name = req.POST.get('name') desc = req.POST.get('desc') if name.strip() and desc.strip(): models.CaseSet.objects.create(name=name, desc=desc) data = {'code': 0, 'msg': '添加成功'} else: data = {'code': -1, 'msg': '参数错误'} return JsonResponse(data) elif req.method == 'PUT': pass elif req.method=='DELETE': pass
3.3 class方式
1 class CaseSet(View): 2 3 def post(self,request): 4 form = CaseSetForm(request.POST) 5 if form.is_valid(): 6 form.save() # 7 # models.CaseSet.objects.create(**form.cleaned_data) 8 data = {'code': 0, 'msg': '添加成功'} 9 else: 10 print(form.errors.as_data()) 11 data = {'code': -1, 'msg': '参数错误'} 12 return JsonResponse(data) 13 14 def get(self,request): 15 case_sets = models.CaseSet.objects.filter(is_delete=False) 16 data = [] 17 for c in case_sets: 18 d = model_to_dict(c) 19 data.append(d) 20 response = {'code': 0, 'msg': '成功', 'data': data} 21 return JsonResponse(response, json_dumps_params={'ensure_ascii': False})
3.4用例接口实现
1 class CaseView(View): 2 def post(self,request): 3 # form = CaseForm(request.POST) 4 form = CaseForm2(request.POST) 5 if form.is_valid(): 6 print('这个是用了form校验的') 7 models.Case.objects.create(**form.cleaned_data) 8 data = {'code': 0, 'msg': '添加成功'} 9 else: 10 print(form.errors.as_data()) 11 data = {'code':-1,'msg':'参数错误'} 12 return JsonResponse(data) 13 14 def get(self,request): 15 case_sets = models.Case.objects.filter(is_delete=False) 16 data = [] 17 for c in case_sets: 18 d = model_to_dict(c) 19 data.append(d) 20 response = {'code': 0, 'msg': '成功', 'data': data} 21 return JsonResponse(response, json_dumps_params={'ensure_ascii': False}) 22 23 def delete(self,request): 24 id = request.GET.get('id') 25 models.Case.objects.filter(id=id).update(is_delete=True) 26 response = {'code': 0, 'msg': '成功'} 27 return JsonResponse(response, json_dumps_params={'ensure_ascii': False}) 28 29 def put(self,request): 30 pass
4、testcase目录下新增个urls.py
1 from django.urls import path 2 from . import views,views_new 3 4 urlpatterns = [ 5 path('add_case_set',views.case_set), 6 path('case_set',views.case_set_all), 7 8 path('case_set_new',views_new.CaseSet.as_view()), 9 path('case',views_new.CaseView.as_view()), 10 11 ]
5、dj_test目录下urls.py配置testcase的urls
6、分页功能的实现views.py
1 def get(self,request): 2 limit = request.GET.get('limit',20) 3 page = request.GET.get('page',1) 4 case_sets = models.Case.objects.filter(is_delete=False) 5 paginator = Paginator(case_sets,limit) 6 page_data = paginator.page(page) 7 data = [] 8 for c in page_data: 9 d = model_to_dict() 10 data.append(d) 11 response = {'code':0,'msg':'','data':data,'count':paginator.count} 12 return JsonResponse(response,json_dumps_params={'ensure_ascii': False})
7、模糊搜索
1 def get(self,request): 2 limit = request.GET.get('limit',20) 3 page = request.GET.get('page',1) 4 search = request.GET.get('search') 5 if search: 6 case_sets= models.Case.objects.filter(Q(title__contains=search)| 7 Q(desc__contains=search)| 8 Q(url__contains=search)| 9 Q(params__contains=search)) 10 else: 11 case_sets = models.Case.objects.filter(is_delete=False) 12 paginator = Paginator(case_sets,limit) 13 page_data = paginator.page(page) 14 data = [] 15 for c in page_data: 16 d = model_to_dict() 17 data.append(d) 18 response = {'code':0,'msg':'','data':data,'count':paginator.count} 19 return JsonResponse(response,json_dumps_params={'ensure_ascii': False})
8、实现按参数过滤
1 from django.db.models import Q 2 def get(self,request): 3 limit = request.GET.get('limit',20) 4 page = request.GET.get('page',1) 5 search = request.GET.get('search') 6 filter_field = ['id','title','method']#支持通过哪些字段来过滤 7 filter_dict = {} 8 for field in filter_field: 9 value = request.GET.get(field)#从请求中获取参数 10 if value: 11 filter_dict[field] = value 12 if filter_dict: 13 case_sets = models.Case.objects.filter(**filter_dict) # 精确查询,优先级高 14 elif search: 15 case_sets= models.Case.objects.filter(Q(title__contains=search)| 16 Q(desc__contains=search)| 17 Q(url__contains=search)| 18 Q(params__contains=search)) 19 else: 20 case_sets = models.Case.objects.filter(is_delete=False) 21 paginator = Paginator(case_sets,limit) 22 page_data = paginator.page(page) 23 data = [] 24 for c in page_data: 25 d = model_to_dict() 26 data.append(d) 27 response = {'code':0,'msg':'','data':data,'count':paginator.count} 28 return JsonResponse(response,json_dumps_params={'ensure_ascii': False})
三、整理代码优化
1 def get_paginator(self,data_list):#实现分页 2 limit = self.request.GET.get('limit',20)#一页要显示多少数据 3 page = self.request.GET.get('page',1)#第几页的数据,默认是第一页 4 paginator = Paginator(data_list, limit) 5 page_data = paginator.page(page)#分页 6 return page_data,paginator 7 8 def get_search_data(self): 9 data = [] 10 search = self.request.GET.get('search') 11 if search: 12 data = models.Case.objects.filter(Q(title__contains=search) | 13 Q(desc__contains=search) | 14 Q(url__contains=search) | 15 Q(params__contains=search) 16 ) 17 return data 18 19 20 def get_filter_data(self): 21 data = [] 22 filter_field = ['id','title','method']#支持通过哪些字段来过滤 23 filter_dict = {} #{'id':1,'title':abc} 24 for field in filter_field: # 25 value = self.request.GET.get(field) 26 if value: 27 filter_dict[field] = value 28 if filter_dict: 29 data = models.Case.objects.filter(**filter_dict) 30 return data
1 def get(self,request): 2 if self.get_filter_data(): 3 case_sets = self.get_filter_data() 4 elif self.get_search_data(): 5 case_sets = self.get_search_data() 6 else: 7 case_sets = models.Case.objects.filter(is_delete=False) #查询所有的 8 page_data,paginator = self.get_paginator(case_sets) 9 data = [] 10 for c in page_data: 11 d = model_to_dict(c) 12 data.append(d) 13 response = {'code': 0, 'msg': '成功', 'data': data,'count':paginator.count} 14 return JsonResponse(response, json_dumps_params={'ensure_ascii': False})