• Django学习笔记(14)form和modelform


    在HTML页面或者请求接口时经常会使用到对参数的校验,django提供了form类和modelform两种用于对参数进行校验的类

    下面例子是基于django前后端分离,后端进行参数校验

    定义models.py   ,定义Case用例表和CaseSet用例集合表

     1 from django.db import models
     2 
     3 # Create your models here.
     4 class BaseModel(models.Model):
     5     create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
     6     update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
     7     is_delete = models.BooleanField(verbose_name='是否删除', default=False)
     8 
     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     class Meta:
    16         db_table = 'case_set'
    17         verbose_name = '用例集合表'
    18         verbose_name_plural = verbose_name
    19 
    20     def __str__(self):
    21          return self.name
    22 
    23 class Case(BaseModel):
    24     title = models.CharField(verbose_name='用例标题',max_length=80,db_index=True,unique=True)
    25     desc = models.CharField(verbose_name='用例描述',max_length=120)
    26     method_choice = [
    27         [0,'get'],
    28         [1,'post'],
    29         [2,'put'],
    30         [3,'delete']
    31     ] #枚举
    32     method = models.SmallIntegerField(choices=method_choice,verbose_name='请求方式',default=0)
    33     url = models.URLField(max_length=50,verbose_name='请求url')
    34     params = models.TextField(verbose_name='请求参数')
    35     run_count = models.IntegerField(verbose_name='运行次数',default=0,null=True,blank=True)
    36     run_time = models.DateTimeField(verbose_name='运行时间',default=None,null=True,blank=True)
    37     case_set = models.ManyToManyField(CaseSet,db_constraint=False,verbose_name='用例集合',null=True,blank=True)
    38 
    39     class Meta:
    40         db_table = 'case'
    41         verbose_name = '用例表'
    42         verbose_name_plural = verbose_name
    43 
    44     def __str__(self):
    45          return self.title

    views.py

      1.使用form校验入参

      使用cvb方式定义CaseSet和CaseView类来返回用例集合和用例,定义CaseSetForm和CaseForm类分别校验case和caseset

     1 from django.core.exceptions import ValidationError
     2 from django.forms import model_to_dict
     3 from django.http import JsonResponse
     4 from django.shortcuts import render
     5 from django.views import View
     6 from django import forms
     7 from . import models
     8 
     9 
    10 #form 参数校验
    11 class CaseForm(forms.Form):#校验参数满足条件,不满足条件时报错
    12     '''校验请求参数'''
    13     title = forms.CharField(max_length=50,min_length=2)   #校验最大长度50,最小长度2
    14     desc = forms.CharField(max_length=60,required=False)
    15     method = forms.IntegerField() #0 1 2 3
    16     url = forms.URLField()
    17     params = forms.CharField(max_length=100)
    18 
    19     #form钩子函数
    20     #校验字段是否在枚举数中
    21     def clean_method(self):#clean_ +字段名----校验单个字段,必须是clean开头
    22         method = self.cleaned_data.get('method')
    23         if method not in (0,1,2,3):
    24             raise ValidationError('method值不对')
    25         return method
    26 
    27     #校验重复性
    28     def clean_title(self):
    29         title = self.cleaned_data.get('title')
    30         if models.Case.objects.filter(title=title).count() > 0:
    31             raise ValidationError('用例标题已存在')
    32         return title
    33 
    34     #检验多个字段
    35     def clean(self):
    36         title = self.cleaned_data.get('title')
    37         desc = self.cleaned_data.get('desc')
    38 
    39 class CaseView(View):
    40     #form校验
    41     def post(self, request):
    42         #form校验
    43         form = CaseForm(request.POST)
    44         if form.is_valid():
    45             # 返回{'title':xxx,'desc':xxx},**组装成{title=xxx,desc=xxx}
    46             models.Case.objects.create(**form.cleaned_data)#将数据存入数据库
    47             data = {'code': 0,'msg': '添加成功'}
    48         else:
    49             print(form.errors.as_json)#打印错误信息
    50             data = {'code': -1,'msg': '参数错误'}
    51         return JsonResponse(data)

      

      2.使用modelform校验入参:上面1中很多参数都是与数据库中的数据紧密相关,而且写了很多类似与models中的代码,可以进一步使用modelform来简化

     1 from django.core.exceptions import ValidationError
     2 from django.http import JsonResponse
     3 from django.views import View
     4 from django import forms
     5 from . import models
     6 
     7 class CaseForm2(forms.ModelForm):#CaseForm2关联Case表的所有字段
     8     class Meta:
     9         fields = '__all__' #__all__代表所有字段都是必传字段
    10         exclude = ['case_set','run_count'] #排除哪些字段
    11         model = models.Case  #关联Case表
    12 
    13 class CaseView(View):
    14  # modelform校验
    15     def post(self, request):
    16         #modelform校验
    17         form = CaseForm2(request.POST)
    18         if form.is_valid():
    19             # 返回{'title':xxx,'desc':xxx}
    20             # cleaned_data读取表单返回的值,返回类型为字典dict型
    21             # models.Case.objects.create(**form.cleaned_data)
    22             form.save()  # form提供save方法,将表单的返回值即form.cleaned_data保存起来
    23             data = {'code':0,'msg':'添加成功'}
    24         else:
    25             print(form.errors.as_json)#打印错误信息
    26             data = {'code':-1,'msg':'参数错误'}
    27         return JsonResponse(data)

    优化:

      将modelform代码从views.py中抽出来,在testcase应用目录下创建forms.py存放form

    forms.py

     1 from django import forms
     2 from django.core.exceptions import ValidationError
     3 from utils.tools import FormatFormError #引入格式化错误信息
     4 
     5 from . import models
     6 class CaseSetForm(forms.ModelForm,FormatFormError):
     7     class Meta:
     8         model = models.CaseSet
     9         exclude = ['is_delete']
    10 
    11 
    12 class CaseForm(forms.ModelForm):
    13     class Meta:
    14         model = models.Case
    15         exclude = ['is_delete','case_set','run_count','run_time']
    16 
    17     #modelform也可以定义钩子方法
    18     def clean_method(self):
    19         pass
    20 
    21 class CaseFormOld(forms.Form):#校验参数满足条件,不满足条件时报错
    22     '''校验请求参数'''
    23     title = forms.CharField(max_length=50,min_length=2)
    24     desc = forms.CharField(max_length=60,required=False)
    25     method = forms.IntegerField() #0 1 2 3
    26     url = forms.URLField()
    27     params = forms.CharField(max_length=100)
    28 
    29     #form钩子函数
    30     #校验字段是否在枚举数中
    31     def clean_method(self):#clean_ +字段名----校验单个字段
    32         method = self.cleaned_data.get('method')
    33         if method not in (0,1,2,3):
    34             raise ValidationError('method值不对')
    35         return method
    36 
    37     #校验重复性
    38     def clean_title(self):
    39         title = self.cleaned_data.get('title')
    40         if models.Case.objects.filter(title=title).count() > 0:
    41             raise ValidationError('用例标题已存在')
    42         return title
    43 
    44     #检验多个字段
    45     def clean(self):
    46         title = self.cleaned_data.get('title')
    47         desc = self.cleaned_data.get('desc')

    views.py

     1 from django.db.models import Q
     2 from django.forms import model_to_dict
     3 from django.http import JsonResponse
     4 from django.core.paginator import Paginator
     5 from . import models
     6 from . import forms
     7 from django.views import View
     8 
     9 class CaseView(View):
    10     def get(self,request):
    11         # 分页
    12         limit = request.GET.get('limit',20)
    13         page = request.GET.get('page',1)
    14         search = request.GET.get('search')#模糊搜索关键字
    15         filter_field = ['id','title','method']#关键字精确查询,通过哪些字段查询
    16         filter_dict = {}
    17         for field in filter_field:
    18             value = request.GET.get(field)
    19             if value:
    20                 filter_dict[field] = value
    21         if filter_dict:
    22             case_sets = models.Case.objects.filter(**filter_dict)
    23         elif search:#模糊查询
    24             case_sets = models.Case.objects.filter(Q(title__contains=search) |
    25                                    Q(desc__contains=search) |
    26                                    Q(url__contains=search) |
    27                                    Q(params__contains=search))#模糊查询
    28         else:
    29             case_sets = models.Case.objects.filter(is_delete=False)#查询所有
    30         paginator = Paginator(case_sets,limit)
    31         page_data = paginator.page(page)
    32 
    33         data = []
    34         for c in page_data:
    35             d = model_to_dict(c)
    36             data.append(d)
    37         response = {'code': 0, 'msg': '添加成功', 'data': data,'count':paginator.count}
    38         return JsonResponse(response, json_dumps_params={'ensure_ascii': False})  # 汉字不转义
    39 
    40 
    41 #form校验
    42     # def post(self, request):
    43     #     #form校验
    44     #     form = CaseForm(request.POST)
    45     #     if form.is_valid():
    46     #         # 返回{'title':xxx,'desc':xxx}
    47     #         models.Case.objects.create(**form.cleaned_data)
    48     #         data = {'code':0,'msg':'添加成功'}
    49     #     else:
    50     #         print(form.errors.as_json)#打印错误信息
    51     #         data = {'code':-1,'msg':'参数错误'}
    52     #     return JsonResponse(data)
    53 
    54     # form校验
    55     def post(self, request):
    56         #modelform校验
    57         form = forms.CaseForm(request.POST)
    58         if form.is_valid():
    59             # 返回{'title':xxx,'desc':xxx}
    60             models.Case.objects.create(**form.cleaned_data)
    61             data = {'code':0,'msg':'添加成功'}
    62         else:
    63             print(form.errors.as_json)#打印错误信息
    64             data = {'code':-1,'msg':'参数错误'}
    65         return JsonResponse(data)
    66 
    67 
    68 
    69     def delete(self,request):
    70         id = request.GET.get('id')
    71         models.Case.objects.filter(id=id).update(is_delete=True)
    72         response = {'code': 0, 'msg': '成功'}
    73         return JsonResponse(response, json_dumps_params={'ensure_ascii': False})  # 汉字不转义
    74 
    75     def put(self,request):
    76         pass
    77 
    78 class CaseSet(View):
    79     def get(self):
    80         case_sets = models.CaseSet.objects.filter(is_delete=False)
    81         data = []
    82         for c in case_sets:
    83             d = model_to_dict(c)
    84             data.append(d)
    85         response = {'code': 0, 'msg': '添加成功', 'data': data}
    86         return JsonResponse(response, json_dumps_params={'ensure_ascii': False})  # 汉字不转义
    87 
    88     def post(self, request):
    89         form = forms.CaseSetForm(request.POST)
    90         if form.is_valid():#form返回为真
    91             # models.CaseSet.objects.create(**form.cleaned_data)
    92             form.save() #form提供save方法,字段存入数据库中,同上一行create操作
    93             data = {'code': 0, 'msg': '添加成功'}
    94         else:
    95             print(form.errors.as_json)
    96             data = {'code': -1, 'msg': form.error_msg}
    97         return JsonResponse(data)  # 通过JsonResponse类返回json字符串

    urls.py

    1 from django.urls import path
    2 from . import views
    3 
    4 urlpatterns = [
    5     path('case',views.CaseView.as_view()) #cvb
    6  
    7 ]
  • 相关阅读:
    linux下使用tar命令
    ContentType和@ResponseBody
    ActiveMQ两种模式PTP和PUB/SUB<转>
    Postgresql分表与优化
    PostgreSQL存储过程<转>
    PostgreSQL Table Partitioning<转>
    Postgresql查询表的大小
    Postgresql添加/删除触发器示例
    Android TextView 支持的HTML标签
    我只是一直很努力
  • 原文地址:https://www.cnblogs.com/bugoobird/p/13371092.html
Copyright © 2020-2023  润新知