自动化测试平台-用例列表的增删改查
模型
models.py:
from django.db import models # Create your models here. class It(models.Model): """接口项目表""" it_name = models.CharField(max_length=32, default="", verbose_name="项目名称") it_desc = models.TextField(max_length=255, default="", verbose_name="项目描述") it_start_time = models.DateField(verbose_name="项目开始时间") it_end_time = models.DateField(verbose_name="项目结束时间") def __str__(self): return self.it_name class Api(models.Model): """接口用例表""" api_sub_it = models.ForeignKey(to="It", verbose_name="所属接口项目", on_delete=models.SET_NULL, blank=True, null=True) api_name = models.CharField(max_length=32, default="", verbose_name="用例名称") api_desc = models.CharField(max_length=255, default="", verbose_name="用例描述") api_url = models.CharField(max_length=255, default="", verbose_name="请求URL") api_method = models.CharField(max_length=32, default='', verbose_name='请求类型') api_params = models.CharField(max_length=255, default={}, verbose_name='请求参数') api_data = models.CharField(max_length=255, default={}, verbose_name='请求data') api_expect = models.CharField(max_length=4196, default={}, verbose_name='预期结果') api_report = models.TextField(verbose_name="测试报告", default="") api_run_time = models.DateTimeField(null=True, verbose_name="执行时间") api_pass_status_choices = ( (0, "未通过"), (1, "已通过") ) api_pass_status = models.IntegerField(choices=api_pass_status_choices, verbose_name="执行是否通过", default=0) api_run_status_choices = ( (0, '未执行'), (1, '已执行'), ) api_run_status = models.IntegerField(choices=api_run_status_choices, verbose_name='是否执行', default=0) def __str__(self): return self.api_name
数据迁移:
python manage.py makemigrations
python manage.py migrate
modelform
mymodelform.py:
from django.forms import ModelForm from django import forms from django.forms import widgets as wid from app01 import models class ItModelForm(ModelForm): class Meta: model = models.It fields = "__all__" # 法2 labels = { "it_name": "项目名称", "it_desc": "项目描述", "it_start_tile": "项目开始时间", "it_end_tile": "项目结束时间", } error_messages = { "it_name": {"required": "不能为空"}, "it_desc": {"required": "不能为空"}, "it_start_tile": {"required": "不能为空"}, "it_end_tile": {"required": "不能为空"}, } widgets = { "it_name": wid.Input(attrs={"class": "form-control", "placeholder": "输入项目名称"}), "it_desc": wid.Textarea(attrs={"class": "form-control", "placeholder": "输入项目名称"}), "it_start_time": wid.DateInput(attrs={"class": "form-control", 'type': "date"}), "it_end_time": wid.DateInput(attrs={"class": "form-control", 'type': "date"}), } # 法一 # bootstrapClass_filter = ['it_start_time', 'it_end_time'] # it_start_time = forms.DateField(label="开始时间", widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"})) # it_end_time = forms.DateField(label="结束时间", widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"})) # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # for name, field in self.fields.items(): # if name in self.bootstrapClass_filter: # continue # old_class = field.widget.attrs.get('class', "") # field.widget.attrs['class'] = '{} form-control'.format(old_class) # field.widget.attrs['placeholder'] = '请输入%s' % (field.label,) class ApiModelForm(ModelForm): """ 用例表 """ class Meta: model = models.Api fields = "__all__" # 这些字段不用展示 exclude = ['api_run_status', 'api_run_time', 'api_pass_status', 'api_report', 'api_sub_it'] bootstrapClass_filter = ['api_run_status', 'api_run_time', 'api_pass_status', 'api_report'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for name, field in self.fields.items(): if name in self.bootstrapClass_filter: continue old_class = field.widget.attrs.get('class', "") field.widget.attrs['class'] = '{} form-control'.format(old_class) field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)
路由
urls.py:
from django.contrib import admin from django.urls import path, re_path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.index, name="index"), path('index/', views.index, name="index"), path('add_it/', views.add_it, name='add_it'), re_path(r'^edit_it/(?P<pk>\d+)$', views.edit_it, name='edit_it'), re_path(r'^delete_it/(?P<pk>\d+)$', views.delete_it, name='delete_it'), # 接口用例表相关 re_path(r'^list_api/(?P<pk>\d+)$', views.list_api, name='list_api'), re_path(r'^add_api/(?P<pk>\d+)$', views.add_api, name='add_api'), re_path(r'^edit_api/(?P<pk>\d+)$', views.edit_api, name='edit_api'), re_path(r'^delete_api/(?P<pk>\d+)$', views.delete_api, name='delete_api'), ]
视图
views.py:
from django.shortcuts import render, HttpResponse, redirect from django.http import JsonResponse from app01 import models from utils.MyModelForm import ItModelForm, ApiModelForm def index(request): """ 项目主页 """ if request.method == "POST": return JsonResponse({"code": 0, "message": "项目主页的post请求,非法"}) else: it_obj = models.It.objects.all() # print(1111111, it_obj) return render(request, 'index.html', {"it_obj": it_obj}) def add_it(request): """ 添加项目 """ if request.method == "POST": form_data = ItModelForm(request.POST) if form_data.is_valid(): form_data.save() return redirect('/index/') else: return render(request, 'add_it.html', {"it_form_obj": form_data}) else: it_form_obj = ItModelForm() return render(request, 'add_it.html', {"it_form_obj": it_form_obj}) def edit_it(request, pk): """ 编辑项目, pk:项目的pk """ it_obj = models.It.objects.filter(pk=pk).first() if request.method == "POST": form_data = ItModelForm(request.POST, instance=it_obj) if form_data.is_valid(): form_data.save() return redirect('/index/') else: return render(request, 'add_it.html', {"it_form_obj": form_data}) else: it_form_obj = ItModelForm(instance=it_obj) return render(request, 'edit_it.html', {"it_form_obj": it_form_obj}) def delete_it(request, pk): """ 删除项目表记录,pk:项目的pk """ models.It.objects.filter(pk=pk).delete() return redirect('/index/') '''用例列表''' def list_api(request, pk): """ 思考:要不要有 pk ? pk:项目的pk 查看某一个项目下的用例列表 """ api_obj = models.Api.objects.filter(api_sub_it_id=pk) it_obj = models.It.objects.filter(pk=pk).first() # print(1111111, it_obj.it_name) return render(request, 'list_api.html', {"api_obj": api_obj, 'it_obj': it_obj}) def add_api(request, pk): """ 添加用例, pk:所属项目的pk """ if request.method == "POST": form_data = ApiModelForm(request.POST) if form_data.is_valid(): print(form_data.instance.__dict__) form_data.instance.__dict__['api_sub_it_id'] = pk # form_data.instance.api_sub_it = it_obj form_data.save() return redirect('/index/') else: return render(request, 'add_api.html', {"api_form_obj": form_data}) else: api_form_obj = ApiModelForm() it_obj = models.It.objects.filter(pk=pk).first() return render(request, 'add_api.html', {"api_form_obj": api_form_obj, "it_obj": it_obj}) def edit_api(request, pk): """ 编辑用例, pk:api的pk """ api_obj = models.Api.objects.filter(pk=pk).first() if request.method == "POST": form_data = ApiModelForm(request.POST, instance=api_obj) if form_data.is_valid(): form_data.save() return redirect('/list_api/{}'.format(api_obj.api_sub_it_id)) # 用例列表接口需要所属项目的pk值 else: return render(request, 'edit_api.html', {"api_form_obj": form_data}) else: api_form_obj = ApiModelForm(instance=api_obj) return render(request, 'edit_api.html', {"api_form_obj": api_form_obj, "it_obj": api_obj.api_sub_it}) def delete_api(request, pk): """ 删除用例, pk:用例的pk """ # 由于返回时,需要项目的pk值,这里不能直接删除 api_obj = models.Api.objects.filter(pk=pk).first() # 获取所属项目的pk it_obj_pk = api_obj.api_sub_it_id api_obj.delete() return redirect('/list_api/{}'.format(it_obj_pk))
模板
index.html:
{% extends 'base.html' %}
{% block breadcrumb %}
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'index' %}">Index</a></li>
<li class="breadcrumb-item active">项目列表</li>
</ol>
{% endblock %}
{#{% if it_obj %}#}
{# {{ it_obj.0.it_name }}#}
{#{% endif %}#}
{##}
{#{% if it_obj %}#}
{# <!-- 如果项目表有数据,就展示 -->#}
{# aaaaaa#}
{#{% else %}#}
{##}
{# {% block content-head %}#}
{##}
{# 没有数据,去 <a href="{% url 'add_it' %}">创建</a> {{ it_obj.0.it_name }}#}
{# {% endblock %}#}
{##}
{#{% endif %}#}
{% block content %}
{# <div class="card card-primary card-outline">#}
{# <div class="card-header">#}
{# <a href="{% url 'add_it' %}">添加项目</a>#}
{# </div>#}
{# </div>#}
{% if it_obj %}
<div class="card card-primary">
<div class="card-header">
<a href="{% url 'add_it' %}">添加项目</a>
</div>
<table class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>序号</th>
<th>名称</th>
<th>描述</th>
<th>开始时间</th>
<th>结束时间</th>
<th>用例数据</th>
<th>覆盖率</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for foo in it_obj %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ foo.it_name }}</td>
<td>{{ foo.it_desc }}</td>
<td>{{ foo.it_start_time }}</td>
<td>{{ foo.it_end_time }}</td>
<td>{{ foo.api_set.count }}</td>
<td>{{ foo.xxoo }}</td> <!--用例通过的数量 除以 总用例数量-->
<td>
<a href="{% url 'delete_it' foo.pk %}" class="btn btn-danger btn-sm">删除</a>
<a href="{% url 'edit_it' foo.pk %}" class="btn btn-info btn-sm">编辑</a>
<a href="{% url 'add_api' foo.pk %}" class="btn btn-warning btn-sm">添加用例</a>
<a href="{% url 'list_api' foo.pk %}" class="btn btn-success btn-sm">查看用例列表</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
没有数据,去 <a href="{% url 'add_it' %}">创建</a>
{% endif %}
{% endblock %}
