django项目实战二(django+bootstrap实现增删改查)进阶查询

news2024/9/20 20:41:37

目录

一、用例管理模块实现

1、创建表和数据

2、创建用例列表

1)注册url(用例列表)

2)修改views.py新增case_list方法

3)layout.html导航条新增一个用例管理

4)新增case_list.html页面

 3、新增用例页面开发

1)新增url case/add/

2)views.py新增CaseModelForm类和add_case方法

3)新增add_case.html页面

4、编辑用例开发

1)注册url

2)实现views.py,新增类CaseEditModelForm与case_edit方法

3)新增case_edit.html页面

5、删除用例

1)注册url

2)修改views.py新增case_delete方法

6、实现查询功能

1)修改views.py

2)修改case_list.html


接上一篇《django项目实战一(django+bootstrap实现增删改查)》

知识点:

        列表将数据库None值显示为空

        新增时使用钩子函数判重

        字段多时,显示全部字段或者不显示哪个字段

        字段显示,但是不可编辑

        编辑时使用钩子函数判重(先得排除自己的判重)

        实现查询功能

        数据库查询知识点,大于、小于、以XX开始、以XX结尾、包含XX等

        查询时查询条件保留

一、用例管理模块实现

1、创建表和数据

1)models.py 新增类Case

from django.db import models

# Create your models here.


class Department(models.Model):
    """部门表"""
    name = models.CharField(verbose_name='部门名称', max_length=20)

    def __str__(self):
        return self.name


class UserInfo(models.Model):
    """员工表"""
    name = models.CharField(verbose_name='姓名', max_length=20)
    password = models.CharField(verbose_name='密码', max_length=64)
    age = models.IntegerField(verbose_name='年龄')
    gender_choices = ((1, '男'), (2, '女'))
    gender = models.SmallIntegerField(verbose_name='性别',choices=gender_choices)
    account = models.DecimalField(verbose_name='账户余额', max_digits=10, decimal_places=2,default=0)
    # create_time = models.DateTimeField(verbose_name='入职时间')
    create_time = models.DateField(verbose_name='入职时间')
    # depart会自动生成字段为depart_id
    # 级联删除 on_delete=models.CASCADE
    # 置空 on_delete=models.SET_NULL 但是必须和null=True, blank=True配合使用,因为你得支持为null
    depart = models.ForeignKey(verbose_name='所属部门', to='Department', to_field='id', on_delete=models.CASCADE)


class Case(models.Model):
    """测试用例表"""
    number = models.CharField(verbose_name='用例编号', max_length=11)
    bug_no = models.IntegerField(verbose_name='缺陷编号', null=True, blank=True)
    name = models.CharField(verbose_name='用例名称', max_length=20)
    step = models.CharField(verbose_name='步骤', max_length=150)
    expect = models.CharField(verbose_name='期望结果', max_length=100)
    actual = models.CharField(verbose_name='实际结果', max_length=100)
    author = models.CharField(verbose_name='作者', max_length=20)
    priority_choices = (
        (1, 'P0'),
        (2, 'P1'),
        (3, 'P2'),
        (4, 'P3'),
    )
    priority = models.SmallIntegerField(verbose_name='优先级', choices=priority_choices, default=1)
    status_choices = (
        (1, '未执行'),
        (2, '通过'),
        (3, '未通过'),
    )
    status = models.SmallIntegerField(verbose_name='状态', choices=status_choices, default=1)

2)执行命令

python manage.py makemigrations 
python manage.py migrate

3)创建几条数据

2、创建用例列表

1)注册url(用例列表)

"""DjangoDemoOne URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from TestManagementSystem import views

urlpatterns = [
    # path('admin/', admin.site.urls),
    # 部门管理
    path('depart/list/', views.depart_list),
    path('depart/add/', views.depart_add),
    path('depart/delete/', views.depart_delete),
    path('depart/<int:nid>/edit/', views.depart_edit),
    # 用户管理
    path('user/list/', views.user_list),
    path('user/add/', views.user_add),
    path('user/model/form/add/', views.user_model_form_add),  # 新方法实现
    path('user/<int:nid>/edit/', views.user_edit),
    path('user/<int:nid>/delete/', views.user_delete), # 与部门删除方式不一样
    # 用例管理
    path('case/list/', views.case_list),
]

2)修改views.py新增case_list方法

from django.shortcuts import render, redirect, HttpResponse
from TestManagementSystem import models
from django import forms
# Create your views here.


def depart_list(request):
    """部门列表"""
    # 查询所有部门
    print("部门列表")
    depart_set = models.Department.objects.all()
    return render(request, 'depart_list.html', {"depart_set": depart_set})


def depart_add(request):
    """新增部门"""
    # 新增部门
    # return HttpResponse("成功")
    if request.method =='GET':
        return render(request, 'depart_add.html')
    depart_name = request.POST.get("departname")
    models.Department.objects.create(name=depart_name)
    return redirect('/depart/list')


def depart_delete(request):
    """删除部门"""
    depart_id = request.GET.get("departid")
    models.Department.objects.filter(id=depart_id).delete()
    return redirect('/depart/list')


def depart_edit(request, nid):
    """编辑部门"""
    if request.method == 'GET':
        row_object = models.Department.objects.filter(id=nid).first()
         # print(row_object.id, row_object.name)
        return render(request, 'depart_edit.html', {"row_object": row_object})
    # 获取用户提交的部门名称
    edit_depart_name = request.POST.get("departname")
    # 根据编辑页面用户ID去更新部门的名称
    models.Department.objects.filter(id=nid).update(name=edit_depart_name)
    return redirect('/depart/list')


def user_list(request):
    """用户列表"""
    # 查询所有用户
    user_set = models.UserInfo.objects.all()
    """
    for obj in user_set:
        print(obj.id, obj.name, obj.password, obj.account, obj.create_time.strftime("%Y-%m-%d-%H-%M-%S"),
              obj.get_gender_display(), obj.depart.name)
    """
    return render(request, 'user_list.html', {"user_set": user_set})


def user_add(request):
    """新增用户(原始方式)"""

    if request.method == 'GET':
        # 这个是为了新增页面动态获取性别
        context = {
            "gender_choices": models.UserInfo.gender_choices,
            "depart_list": models.Department.objects.all()
        }
        return render(request, 'user_add.html', context)
    user_name = request.POST.get("username")
    password = request.POST.get("pwd")
    age = request.POST.get("age")
    account = request.POST.get("ac")
    create_time = request.POST.get("ctime")
    gender = request.POST.get("gd")
    depart_id = request.POST.get("dp")
    models.UserInfo.objects.create(name=user_name, password=password,
                                   age=age, account=account,
                                   create_time=create_time,
                                   gender=gender, depart_id=depart_id)
    return redirect('/user/list')


class UserModelForm(forms.ModelForm):
    # 限制姓名的长度,至少为3位
    name = forms.CharField(min_length=3, label='用户名')
    # password = forms.CharField(label='密码',validators='这里写正则表达式')

    class Meta:
        model = models.UserInfo
        fields = ["name", "password", "age", "account", "create_time", "gender", "depart"]
        '''widgets = {
            "name": forms.TextInput(attrs={"class": "form-control"}),
            "password": forms.PasswordInput(attrs={"class": "form-control"}),
            "age": forms.TextInput(attrs={"class": "form-control"}),
            "account": forms.TextInput(attrs={"class": "form-control"})           
        }'''  # 下方方法更好

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}


def user_model_form_add(request):
    """新增用户(ModelForm方式)"""

    if request.method == 'GET':
        form = UserModelForm()
        return render(request, 'user_model_form_add.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        form.save()
        return redirect('/user/list')
    # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_model_form_add.html', {"form": form})


def user_edit(request, nid):
    """编辑用户"""
    # 根据nid去数据库获取所在行数据
    row_object = models.UserInfo.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = UserModelForm(instance=row_object)
        return  render(request, 'user_edit.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        # form.instance.字段名=值  # 如果需要存储用户输入之外的值使用这个
        form.save()
        return redirect('/user/list')
        # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_edit.html', {"form": form})


def user_delete(request, nid):
    """删除用户"""
    # 根据nid去数据库获取所在行数据进行删除
    models.UserInfo.objects.filter(id=nid).delete()
    return redirect('/user/list')


def case_list(request):
    """用例列表"""
    # 查询所有用例
    case_set = models.Case.objects.all().order_by('-id')
    return render(request, 'case_list.html', {"case_set": case_set})

3)layout.html导航条新增一个用例管理

知识点:将数据库当中为None数据在列表显示为空

<td>{{ obj.actual|default_if_none:"&nbsp;" }}</td>
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% block title %}{% endblock %}
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}"/>
    <style>
        .navbar{
            border-radius: 0;
        }
    </style>
</head>
<body>


<nav class="navbar navbar-default">
    <div class="container">  <!-- <div class="container-fluid">  -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">测试管理系统</a>
        </div>
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li><a href="/depart/list/">部门管理</a></li>
                <li><a href="/user/list/">用户管理</a></li>
                <li><a href="/case/list/">用例管理</a></li>
            </ul>

            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">登录</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">春天的菠菜 <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">个人资料</a></li>
                        <li><a href="#">我的信息</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">注销</a></li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
</nav>

<div>

    {% block content %}{% endblock %}

</div>


<script src="{% static 'js/jquery-3.6.3.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.js' %}"></script>
</body>
</html>

4)新增case_list.html页面

{% extends 'layout.html' %}
{% block title %}
    <title>用例列表</title>
{% endblock %}
{% block content %}
    <div class="container">
        <div style="margin-bottom: 10px">
            <a class="btn btn-success" href="/case/add/">
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
                新建
            </a>
        </div>

        <div class="bs-example" data-example-id="panel-without-body-with-table">
            <div class="panel panel-default">
                <!-- Default panel contents -->
                <div class="panel-heading">
                    <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
                    用例列表
                </div>

                <!-- Table -->
                <table class="table table-bordered">
                    <thead>
                    <tr>
                        <th>序号</th>
                        <th>用例编号</th>
                        <th>用例名称</th>
                        <th>步骤</th>
                        <th>期望结果</th>
                        <th>实际结果</th>
                        <th>优先级</th>
                        <th>作者</th>
                        <th>状态</th>
                        <th>缺陷编号</th>
                        <th>操作</th>

                    </tr>
                    </thead>
                    <tbody>
                    {% for obj in case_set %}
                        <tr>
                            <th scope="row">{{ obj.id }}</th>
                            <td>{{ obj.number }}</td>
                            <td>{{ obj.name }}</td>
                            <td>{{ obj.step }}</td>
                            <td>{{ obj.expect }}</td>
                            <td>{{ obj.actual|default_if_none:"&nbsp;"  }}</td>
                            <td>{{ obj.get_priority_display }}</td>
                            <td>{{ obj.author }}</td>
                            <td>{{ obj.get_status_display }}</td>
                            <td>{{ obj.bug_no|default_if_none:"&nbsp;"  }}</td>
                            <td>
                                <a class="btn btn-primary btn-xs" href="/case/{{ obj.id }}/edit/">编辑</a>
                                <a class="btn btn-danger btn-xs" href="/case/{{ obj.id }}/delete/">删除</a>
                            </td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>


    </div>

{% endblock %}

 3、新增用例页面开发

1)新增url case/add/


from django.contrib import admin
from django.urls import path
from TestManagementSystem import views

urlpatterns = [
    # path('admin/', admin.site.urls),
    # 部门管理
    path('depart/list/', views.depart_list),
    path('depart/add/', views.depart_add),
    path('depart/delete/', views.depart_delete),
    path('depart/<int:nid>/edit/', views.depart_edit),
    # 用户管理
    path('user/list/', views.user_list),
    path('user/add/', views.user_add),
    path('user/model/form/add/', views.user_model_form_add),  # 新方法实现
    path('user/<int:nid>/edit/', views.user_edit),
    path('user/<int:nid>/delete/', views.user_delete), # 与部门删除方式不一样
    # 用例管理
    path('case/list/', views.case_list),
    path('case/add/', views.case_add),
]

2)views.py新增CaseModelForm类和add_case方法

这个有个新增的知识点,

第一个是:新增判重,注意是在CaseModelForm新增一个方法,方法名是clean_加字段名(你要控制判重的字段)

 # 钩子函数进行判重验证,这个名字注意是clean_加字段名
    def clean_number(self):    
        tex_number = self.cleaned_data['number']
        exists = models.Case.objects.filter(number=tex_number).exists()
        if exists:
            raise ValidationError("用例编号已存在")
        return tex_number

第二个是:显示全部字段或者排除显示某个字段

fields = "__all__"  # 这个表示所有字段
# exclude = ["bug_no"] #  排除字段
from django.shortcuts import render, redirect, HttpResponse
from TestManagementSystem import models
from django import forms
from django.core.validators import RegexValidator
# Create your views here.


def depart_list(request):
    """部门列表"""
    # 查询所有部门
    print("部门列表")
    depart_set = models.Department.objects.all()
    return render(request, 'depart_list.html', {"depart_set": depart_set})


def depart_add(request):
    """新增部门"""
    # 新增部门
    # return HttpResponse("成功")
    if request.method =='GET':
        return render(request, 'depart_add.html')
    depart_name = request.POST.get("departname")
    models.Department.objects.create(name=depart_name)
    return redirect('/depart/list')


def depart_delete(request):
    """删除部门"""
    depart_id = request.GET.get("departid")
    models.Department.objects.filter(id=depart_id).delete()
    return redirect('/depart/list')


def depart_edit(request, nid):
    """编辑部门"""
    if request.method == 'GET':
        row_object = models.Department.objects.filter(id=nid).first()
         # print(row_object.id, row_object.name)
        return render(request, 'depart_edit.html', {"row_object": row_object})
    # 获取用户提交的部门名称
    edit_depart_name = request.POST.get("departname")
    # 根据编辑页面用户ID去更新部门的名称
    models.Department.objects.filter(id=nid).update(name=edit_depart_name)
    return redirect('/depart/list')


def user_list(request):
    """用户列表"""
    # 查询所有用户
    user_set = models.UserInfo.objects.all()
    """
    for obj in user_set:
        print(obj.id, obj.name, obj.password, obj.account, obj.create_time.strftime("%Y-%m-%d-%H-%M-%S"),
              obj.get_gender_display(), obj.depart.name)
    """
    return render(request, 'user_list.html', {"user_set": user_set})


def user_add(request):
    """新增用户(原始方式)"""

    if request.method == 'GET':
        # 这个是为了新增页面动态获取性别
        context = {
            "gender_choices": models.UserInfo.gender_choices,
            "depart_list": models.Department.objects.all()
        }
        return render(request, 'user_add.html', context)
    user_name = request.POST.get("username")
    password = request.POST.get("pwd")
    age = request.POST.get("age")
    account = request.POST.get("ac")
    create_time = request.POST.get("ctime")
    gender = request.POST.get("gd")
    depart_id = request.POST.get("dp")
    models.UserInfo.objects.create(name=user_name, password=password,
                                   age=age, account=account,
                                   create_time=create_time,
                                   gender=gender, depart_id=depart_id)
    return redirect('/user/list')


class UserModelForm(forms.ModelForm):
    # 限制姓名的长度,至少为3位
    name = forms.CharField(min_length=3, label='用户名')
    # password = forms.CharField(label='密码',validators='这里写正则表达式')

    class Meta:
        model = models.UserInfo
        fields = ["name", "password", "age", "account", "create_time", "gender", "depart"]
        '''widgets = {
            "name": forms.TextInput(attrs={"class": "form-control"}),
            "password": forms.PasswordInput(attrs={"class": "form-control"}),
            "age": forms.TextInput(attrs={"class": "form-control"}),
            "account": forms.TextInput(attrs={"class": "form-control"})           
        }'''  # 下方方法更好

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}


def user_model_form_add(request):
    """新增用户(ModelForm方式)"""

    if request.method == 'GET':
        form = UserModelForm()
        return render(request, 'user_model_form_add.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        form.save()
        return redirect('/user/list')
    # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_model_form_add.html', {"form": form})


def user_edit(request, nid):
    """编辑用户"""
    # 根据nid去数据库获取所在行数据
    row_object = models.UserInfo.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = UserModelForm(instance=row_object)
        return  render(request, 'user_edit.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        # form.instance.字段名=值  # 如果需要存储用户输入之外的值使用这个
        form.save()
        return redirect('/user/list')
        # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_edit.html', {"form": form})


def user_delete(request, nid):
    """删除用户"""
    # 根据nid去数据库获取所在行数据进行删除
    models.UserInfo.objects.filter(id=nid).delete()
    return redirect('/user/list')


def case_list(request):
    """用例列表"""
    # 查询所有用例
    case_set = models.Case.objects.all().order_by('-id')
    return render(request, 'case_list.html', {"case_set": case_set})


class CaseModelForm(forms.ModelForm):
    number = forms.CharField(
        label="用例编号",
        validators=[RegexValidator(r'^0\d{3}$', '数字必须以0开头的4位数字')],
    )

    class Meta:
        model = models.Case
        # fields = ["number", "name", "step", "expect", "actual", "priority", "author", "status", "bug_no"]
        fields = "__all__"  # 这个表示所有字段
        # exclude = ["bug_no"] #  排除字段

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}
   # 钩子函数进行判重验证,这个名字注意是clean_加字段名
    def clean_number(self):
        tex_number = self.cleaned_data['number']
        exists = models.Case.objects.filter(number=tex_number).exists()
        if exists:
            raise ValidationError("用例编号已存在")
        return tex_number


def case_add(request):
    """新增用例(ModelForm方式)"""
    if request.method == 'GET':
        form = CaseModelForm()
        return render(request, 'case_add.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = CaseModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        form.save()
        return redirect('/case/list')
    # 如果不满足if判断进入到else返回错误信息
    return render(request, 'case_add.html', {"form": form})

3)新增add_case.html页面

{% extends 'layout.html' %}
{% block title %}
    <title>新增用例(ModelForm)</title>
{% endblock %}
{% block content %}
 <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">新增用例</h3>
            </div>
            <div class="panel-body">
                <form method="post" novalidate>
                    {% csrf_token %}
                    {% for field in form %}
                        <div class="form-group">
                            <label>{{ field.label }}</label>
                            {{ field }}
                            <span style="color: red">{{ field.errors.0 }}</span>
                        </div>
                    {% endfor %}

                    <button type="submit" class="btn btn-primary">保 存</button>
                </form>
            </div>
        </div>

    </div>

{% endblock %}

4、编辑用例开发

1)注册url

from django.contrib import admin
from django.urls import path
from TestManagementSystem import views

urlpatterns = [
    # path('admin/', admin.site.urls),
    # 部门管理
    path('depart/list/', views.depart_list),
    path('depart/add/', views.depart_add),
    path('depart/delete/', views.depart_delete),
    path('depart/<int:nid>/edit/', views.depart_edit),
    # 用户管理
    path('user/list/', views.user_list),
    path('user/add/', views.user_add),
    path('user/model/form/add/', views.user_model_form_add),  # 新方法实现
    path('user/<int:nid>/edit/', views.user_edit),
    path('user/<int:nid>/delete/', views.user_delete), # 与部门删除方式不一样
    # 用例管理
    path('case/list/', views.case_list),
    path('case/add/', views.case_add),
    path('case/<int:nid>/edit/', views.case_edit),
]

2)实现views.py,新增类CaseEditModelForm与case_edit方法

这里新增了一个类CaseEditModelForm来控制显示字段,有2个知识点:

第一个是直接设置字段,未设置就不显示

fields = ["number",  "actual",  "bug_no"]

 

 第二个是字段显示,但是不可编辑 

 # 控制字段显示,但是不可编辑
    number = forms.CharField(disabled=True, label="用例编号")  

 第三个是修改判重,CaseEditModelForm新增钩子方法clean_+判重字段,注意这里的判重要排除自己

    # 钩子函数进行判重验证,这个名字注意是clean_加字段名
    def clean_number(self):
        # 获取当前编辑那一行的ID,从POST那里获取到了instance
        # print(self.instance.pk)
        tex_number = self.cleaned_data['number']
        exists = models.Case.objects.exclude(id=self.instance.pk).filter(number=tex_number).exists()
        if exists:
            raise ValidationError("用例编号已存在")
        return tex_number

from django.core.exceptions import ValidationError
from django.shortcuts import render, redirect, HttpResponse
from TestManagementSystem import models
from django import forms
from django.core.validators import RegexValidator
# Create your views here.


def depart_list(request):
    """部门列表"""
    # 查询所有部门
    print("部门列表")
    depart_set = models.Department.objects.all()
    return render(request, 'depart_list.html', {"depart_set": depart_set})


def depart_add(request):
    """新增部门"""
    # 新增部门
    # return HttpResponse("成功")
    if request.method =='GET':
        return render(request, 'depart_add.html')
    depart_name = request.POST.get("departname")
    models.Department.objects.create(name=depart_name)
    return redirect('/depart/list')


def depart_delete(request):
    """删除部门"""
    depart_id = request.GET.get("departid")
    models.Department.objects.filter(id=depart_id).delete()
    return redirect('/depart/list')


def depart_edit(request, nid):
    """编辑部门"""
    if request.method == 'GET':
        row_object = models.Department.objects.filter(id=nid).first()
         # print(row_object.id, row_object.name)
        return render(request, 'depart_edit.html', {"row_object": row_object})
    # 获取用户提交的部门名称
    edit_depart_name = request.POST.get("departname")
    # 根据编辑页面用户ID去更新部门的名称
    models.Department.objects.filter(id=nid).update(name=edit_depart_name)
    return redirect('/depart/list')


def user_list(request):
    """用户列表"""
    # 查询所有用户
    user_set = models.UserInfo.objects.all()
    """
    for obj in user_set:
        print(obj.id, obj.name, obj.password, obj.account, obj.create_time.strftime("%Y-%m-%d-%H-%M-%S"),
              obj.get_gender_display(), obj.depart.name)
    """
    return render(request, 'user_list.html', {"user_set": user_set})


def user_add(request):
    """新增用户(原始方式)"""

    if request.method == 'GET':
        # 这个是为了新增页面动态获取性别
        context = {
            "gender_choices": models.UserInfo.gender_choices,
            "depart_list": models.Department.objects.all()
        }
        return render(request, 'user_add.html', context)
    user_name = request.POST.get("username")
    password = request.POST.get("pwd")
    age = request.POST.get("age")
    account = request.POST.get("ac")
    create_time = request.POST.get("ctime")
    gender = request.POST.get("gd")
    depart_id = request.POST.get("dp")
    models.UserInfo.objects.create(name=user_name, password=password,
                                   age=age, account=account,
                                   create_time=create_time,
                                   gender=gender, depart_id=depart_id)
    return redirect('/user/list')


class UserModelForm(forms.ModelForm):
    # 限制姓名的长度,至少为3位
    name = forms.CharField(min_length=3, label='用户名')
    # password = forms.CharField(label='密码',validators='这里写正则表达式')

    class Meta:
        model = models.UserInfo
        fields = ["name", "password", "age", "account", "create_time", "gender", "depart"]
        '''widgets = {
            "name": forms.TextInput(attrs={"class": "form-control"}),
            "password": forms.PasswordInput(attrs={"class": "form-control"}),
            "age": forms.TextInput(attrs={"class": "form-control"}),
            "account": forms.TextInput(attrs={"class": "form-control"})           
        }'''  # 下方方法更好

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}


def user_model_form_add(request):
    """新增用户(ModelForm方式)"""

    if request.method == 'GET':
        form = UserModelForm()
        return render(request, 'user_model_form_add.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        form.save()
        return redirect('/user/list')
    # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_model_form_add.html', {"form": form})


def user_edit(request, nid):
    """编辑用户"""
    # 根据nid去数据库获取所在行数据
    row_object = models.UserInfo.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = UserModelForm(instance=row_object)
        return  render(request, 'user_edit.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        # form.instance.字段名=值  # 如果需要存储用户输入之外的值使用这个
        form.save()
        return redirect('/user/list')
        # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_edit.html', {"form": form})


def user_delete(request, nid):
    """删除用户"""
    # 根据nid去数据库获取所在行数据进行删除
    models.UserInfo.objects.filter(id=nid).delete()
    return redirect('/user/list')


def case_list(request):
    """用例列表"""
    # 查询所有用例
    case_set = models.Case.objects.all().order_by('-id')
    return render(request, 'case_list.html', {"case_set": case_set})


class CaseModelForm(forms.ModelForm):
    number = forms.CharField(
        label="用例编号",
        validators=[RegexValidator(r'^0\d{3}$', '数字必须以0开头的4位数字')],
    )

    class Meta:
        model = models.Case
        # fields = ["number", "name", "step", "expect", "actual", "priority", "author", "status", "bug_no"]
        fields = "__all__"  # 这个表示所有字段
        # exclude = ["bug_no"] #  排除字段

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

    # 钩子函数进行判重验证,这个名字注意是clean_加字段名
    def clean_number(self):
        tex_number = self.cleaned_data['number']
        exists = models.Case.objects.filter(number=tex_number).exists()
        if exists:
            raise ValidationError("用例编号已存在")
        return tex_number


def case_add(request):
    """新增用例(ModelForm方式)"""
    if request.method == 'GET':
        form = CaseModelForm()
        return render(request, 'case_add.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = CaseModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        form.save()
        return redirect('/case/list')
    # 如果不满足if判断进入到else返回错误信息
    return render(request, 'case_add.html', {"form": form})


class CaseEditModelForm(forms.ModelForm):
    # 控制字段显示,但是不可编辑
    number = forms.CharField(disabled=True, label="用例编号")
    class Meta:
        model = models.Case
        fields = ["number", "name", "step", "expect", "actual", "priority", "author",  "status", "bug_no"]

        # fields = "__all__"  # 这个表示所有字段
        # exclude = ["bug_no"] #  排除字段

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

    # 钩子函数进行判重验证,这个名字注意是clean_加字段名
    def clean_number(self):
        # 获取当前编辑那一行的ID,从POST那里获取到了instance
        # print(self.instance.pk)
        tex_number = self.cleaned_data['number']
        exists = models.Case.objects.exclude(id=self.instance.pk).filter(number=tex_number).exists()
        if exists:
            raise ValidationError("用例编号已存在")
        return tex_number

def case_edit(request, nid):
    """编辑用户"""
    # 根据nid去数据库获取所在行数据
    row_object = models.Case.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = CaseEditModelForm(instance=row_object)
        return  render(request, 'case_edit.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = CaseEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        # form.instance.字段名=值  # 如果需要存储用户输入之外的值使用这个
        form.save()
        return redirect('/case/list')
        # 如果不满足if判断进入到else返回错误信息
    return render(request, 'case_edit.html', {"form": form})

3)新增case_edit.html页面

{% extends 'layout.html' %}
{% block title %}
    <title>编辑用例(ModelForm)</title>
{% endblock %}
{% block content %}
 <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">编辑用例</h3>
            </div>
            <div class="panel-body">
                <form method="post" novalidate>
                    {% csrf_token %}
                    {% for field in form %}
                        <div class="form-group">
                            <label>{{ field.label }}</label>
                            {{ field }}
                            <span style="color: red">{{ field.errors.0 }}</span>
                        </div>
                    {% endfor %}

                    <button type="submit" class="btn btn-primary">保 存</button>
                </form>
            </div>
        </div>

    </div>

{% endblock %}

5、删除用例

1)注册url

from django.contrib import admin
from django.urls import path
from TestManagementSystem import views

urlpatterns = [
    # path('admin/', admin.site.urls),
    # 部门管理
    path('depart/list/', views.depart_list),
    path('depart/add/', views.depart_add),
    path('depart/delete/', views.depart_delete),
    path('depart/<int:nid>/edit/', views.depart_edit),
    # 用户管理
    path('user/list/', views.user_list),
    path('user/add/', views.user_add),
    path('user/model/form/add/', views.user_model_form_add),  # 新方法实现
    path('user/<int:nid>/edit/', views.user_edit),
    path('user/<int:nid>/delete/', views.user_delete), # 与部门删除方式不一样
    # 用例管理
    path('case/list/', views.case_list),
    path('case/add/', views.case_add),
    path('case/<int:nid>/edit/', views.case_edit),
    path('case/<int:nid>/delete/', views.case_delete),
]

2)修改views.py新增case_delete方法

from django.core.exceptions import ValidationError
from django.shortcuts import render, redirect, HttpResponse
from TestManagementSystem import models
from django import forms
from django.core.validators import RegexValidator
# Create your views here.


def depart_list(request):
    """部门列表"""
    # 查询所有部门
    print("部门列表")
    depart_set = models.Department.objects.all()
    return render(request, 'depart_list.html', {"depart_set": depart_set})


def depart_add(request):
    """新增部门"""
    # 新增部门
    # return HttpResponse("成功")
    if request.method =='GET':
        return render(request, 'depart_add.html')
    depart_name = request.POST.get("departname")
    models.Department.objects.create(name=depart_name)
    return redirect('/depart/list')


def depart_delete(request):
    """删除部门"""
    depart_id = request.GET.get("departid")
    models.Department.objects.filter(id=depart_id).delete()
    return redirect('/depart/list')


def depart_edit(request, nid):
    """编辑部门"""
    if request.method == 'GET':
        row_object = models.Department.objects.filter(id=nid).first()
         # print(row_object.id, row_object.name)
        return render(request, 'depart_edit.html', {"row_object": row_object})
    # 获取用户提交的部门名称
    edit_depart_name = request.POST.get("departname")
    # 根据编辑页面用户ID去更新部门的名称
    models.Department.objects.filter(id=nid).update(name=edit_depart_name)
    return redirect('/depart/list')


def user_list(request):
    """用户列表"""
    # 查询所有用户
    user_set = models.UserInfo.objects.all()
    """
    for obj in user_set:
        print(obj.id, obj.name, obj.password, obj.account, obj.create_time.strftime("%Y-%m-%d-%H-%M-%S"),
              obj.get_gender_display(), obj.depart.name)
    """
    return render(request, 'user_list.html', {"user_set": user_set})


def user_add(request):
    """新增用户(原始方式)"""

    if request.method == 'GET':
        # 这个是为了新增页面动态获取性别
        context = {
            "gender_choices": models.UserInfo.gender_choices,
            "depart_list": models.Department.objects.all()
        }
        return render(request, 'user_add.html', context)
    user_name = request.POST.get("username")
    password = request.POST.get("pwd")
    age = request.POST.get("age")
    account = request.POST.get("ac")
    create_time = request.POST.get("ctime")
    gender = request.POST.get("gd")
    depart_id = request.POST.get("dp")
    models.UserInfo.objects.create(name=user_name, password=password,
                                   age=age, account=account,
                                   create_time=create_time,
                                   gender=gender, depart_id=depart_id)
    return redirect('/user/list')


class UserModelForm(forms.ModelForm):
    # 限制姓名的长度,至少为3位
    name = forms.CharField(min_length=3, label='用户名')
    # password = forms.CharField(label='密码',validators='这里写正则表达式')

    class Meta:
        model = models.UserInfo
        fields = ["name", "password", "age", "account", "create_time", "gender", "depart"]
        '''widgets = {
            "name": forms.TextInput(attrs={"class": "form-control"}),
            "password": forms.PasswordInput(attrs={"class": "form-control"}),
            "age": forms.TextInput(attrs={"class": "form-control"}),
            "account": forms.TextInput(attrs={"class": "form-control"})           
        }'''  # 下方方法更好

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}


def user_model_form_add(request):
    """新增用户(ModelForm方式)"""

    if request.method == 'GET':
        form = UserModelForm()
        return render(request, 'user_model_form_add.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        form.save()
        return redirect('/user/list')
    # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_model_form_add.html', {"form": form})


def user_edit(request, nid):
    """编辑用户"""
    # 根据nid去数据库获取所在行数据
    row_object = models.UserInfo.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = UserModelForm(instance=row_object)
        return  render(request, 'user_edit.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        # form.instance.字段名=值  # 如果需要存储用户输入之外的值使用这个
        form.save()
        return redirect('/user/list')
        # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_edit.html', {"form": form})


def user_delete(request, nid):
    """删除用户"""
    # 根据nid去数据库获取所在行数据进行删除
    models.UserInfo.objects.filter(id=nid).delete()
    return redirect('/user/list')


def case_list(request):
    """用例列表"""
    # 查询所有用例
    case_set = models.Case.objects.all().order_by('-id')
    return render(request, 'case_list.html', {"case_set": case_set})


class CaseModelForm(forms.ModelForm):
    number = forms.CharField(
        label="用例编号",
        validators=[RegexValidator(r'^0\d{3}$', '数字必须以0开头的4位数字')],
    )

    class Meta:
        model = models.Case
        # fields = ["number", "name", "step", "expect", "actual", "priority", "author", "status", "bug_no"]
        fields = "__all__"  # 这个表示所有字段
        # exclude = ["bug_no"] #  排除字段

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

    # 钩子函数进行判重验证,这个名字注意是clean_加字段名
    def clean_number(self):
        tex_number = self.cleaned_data['number']
        exists = models.Case.objects.filter(number=tex_number).exists()
        if exists:
            raise ValidationError("用例编号已存在")
        return tex_number


def case_add(request):
    """新增用例(ModelForm方式)"""
    if request.method == 'GET':
        form = CaseModelForm()
        return render(request, 'case_add.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = CaseModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        form.save()
        return redirect('/case/list')
    # 如果不满足if判断进入到else返回错误信息
    return render(request, 'case_add.html', {"form": form})


class CaseEditModelForm(forms.ModelForm):
    # 控制字段显示,但是不可编辑
    number = forms.CharField(disabled=True, label="用例编号")
    class Meta:
        model = models.Case
        fields = ["number", "name", "step", "expect", "actual", "priority", "author",  "status", "bug_no"]

        # fields = "__all__"  # 这个表示所有字段
        # exclude = ["bug_no"] #  排除字段

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

    # 钩子函数进行判重验证,这个名字注意是clean_加字段名
    def clean_number(self):
        # 获取当前编辑那一行的ID,从POST那里获取到了instance
        # print(self.instance.pk)
        tex_number = self.cleaned_data['number']
        exists = models.Case.objects.exclude(id=self.instance.pk).filter(number=tex_number).exists()
        if exists:
            raise ValidationError("用例编号已存在")
        return tex_number

def case_edit(request, nid):
    """编辑用户"""
    # 根据nid去数据库获取所在行数据
    row_object = models.Case.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = CaseEditModelForm(instance=row_object)
        return  render(request, 'case_edit.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = CaseEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        # form.instance.字段名=值  # 如果需要存储用户输入之外的值使用这个
        form.save()
        return redirect('/case/list')
        # 如果不满足if判断进入到else返回错误信息
    return render(request, 'case_edit.html', {"form": form})


def case_delete(request, nid):
    """删除用例"""
    # 根据nid去数据库获取所在行数据进行删除
    models.Case.objects.filter(id=nid).delete()
    return redirect('/case/list')

6、实现查询功能

查询的知识点示例:大于、等于、大于等于、小于等于、以XX开头、以XX结尾、包含XX

1)修改views.py

修改case_list方法

from django.core.exceptions import ValidationError
from django.shortcuts import render, redirect, HttpResponse
from TestManagementSystem import models
from django import forms
from django.core.validators import RegexValidator
# Create your views here.


def depart_list(request):
    """部门列表"""
    # 查询所有部门
    print("部门列表")
    depart_set = models.Department.objects.all()
    return render(request, 'depart_list.html', {"depart_set": depart_set})


def depart_add(request):
    """新增部门"""
    # 新增部门
    # return HttpResponse("成功")
    if request.method =='GET':
        return render(request, 'depart_add.html')
    depart_name = request.POST.get("departname")
    models.Department.objects.create(name=depart_name)
    return redirect('/depart/list')


def depart_delete(request):
    """删除部门"""
    depart_id = request.GET.get("departid")
    models.Department.objects.filter(id=depart_id).delete()
    return redirect('/depart/list')


def depart_edit(request, nid):
    """编辑部门"""
    if request.method == 'GET':
        row_object = models.Department.objects.filter(id=nid).first()
         # print(row_object.id, row_object.name)
        return render(request, 'depart_edit.html', {"row_object": row_object})
    # 获取用户提交的部门名称
    edit_depart_name = request.POST.get("departname")
    # 根据编辑页面用户ID去更新部门的名称
    models.Department.objects.filter(id=nid).update(name=edit_depart_name)
    return redirect('/depart/list')


def user_list(request):
    """用户列表"""
    # 查询所有用户
    user_set = models.UserInfo.objects.all()
    """
    for obj in user_set:
        print(obj.id, obj.name, obj.password, obj.account, obj.create_time.strftime("%Y-%m-%d-%H-%M-%S"),
              obj.get_gender_display(), obj.depart.name)
    """
    return render(request, 'user_list.html', {"user_set": user_set})


def user_add(request):
    """新增用户(原始方式)"""

    if request.method == 'GET':
        # 这个是为了新增页面动态获取性别
        context = {
            "gender_choices": models.UserInfo.gender_choices,
            "depart_list": models.Department.objects.all()
        }
        return render(request, 'user_add.html', context)
    user_name = request.POST.get("username")
    password = request.POST.get("pwd")
    age = request.POST.get("age")
    account = request.POST.get("ac")
    create_time = request.POST.get("ctime")
    gender = request.POST.get("gd")
    depart_id = request.POST.get("dp")
    models.UserInfo.objects.create(name=user_name, password=password,
                                   age=age, account=account,
                                   create_time=create_time,
                                   gender=gender, depart_id=depart_id)
    return redirect('/user/list')


class UserModelForm(forms.ModelForm):
    # 限制姓名的长度,至少为3位
    name = forms.CharField(min_length=3, label='用户名')
    # password = forms.CharField(label='密码',validators='这里写正则表达式')

    class Meta:
        model = models.UserInfo
        fields = ["name", "password", "age", "account", "create_time", "gender", "depart"]
        '''widgets = {
            "name": forms.TextInput(attrs={"class": "form-control"}),
            "password": forms.PasswordInput(attrs={"class": "form-control"}),
            "age": forms.TextInput(attrs={"class": "form-control"}),
            "account": forms.TextInput(attrs={"class": "form-control"})           
        }'''  # 下方方法更好

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}


def user_model_form_add(request):
    """新增用户(ModelForm方式)"""

    if request.method == 'GET':
        form = UserModelForm()
        return render(request, 'user_model_form_add.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        form.save()
        return redirect('/user/list')
    # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_model_form_add.html', {"form": form})


def user_edit(request, nid):
    """编辑用户"""
    # 根据nid去数据库获取所在行数据
    row_object = models.UserInfo.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = UserModelForm(instance=row_object)
        return  render(request, 'user_edit.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = UserModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        # form.instance.字段名=值  # 如果需要存储用户输入之外的值使用这个
        form.save()
        return redirect('/user/list')
        # 如果不满足if判断进入到else返回错误信息
    return render(request, 'user_edit.html', {"form": form})


def user_delete(request, nid):
    """删除用户"""
    # 根据nid去数据库获取所在行数据进行删除
    models.UserInfo.objects.filter(id=nid).delete()
    return redirect('/user/list')


def case_list(request):
    """用例列表"""
    # 查询所有用例
    data_dict = {}
    # 获取浏览器传过来的值
    value = request.GET.get('q')    
    if value:
        data_dict["name__contains"] = value
    case_set = models.Case.objects.filter(**data_dict).order_by('-id')
    return render(request, 'case_list.html', {"case_set": case_set})


class CaseModelForm(forms.ModelForm):
    number = forms.CharField(
        label="用例编号",
        validators=[RegexValidator(r'^0\d{3}$', '数字必须以0开头的4位数字')],
    )

    class Meta:
        model = models.Case
        # fields = ["number", "name", "step", "expect", "actual", "priority", "author", "status", "bug_no"]
        fields = "__all__"  # 这个表示所有字段
        # exclude = ["bug_no"] #  排除字段

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

    # 钩子函数进行判重验证,这个名字注意是clean_加字段名
    def clean_number(self):
        tex_number = self.cleaned_data['number']
        exists = models.Case.objects.filter(number=tex_number).exists()
        if exists:
            raise ValidationError("用例编号已存在")
        return tex_number


def case_add(request):
    """新增用例(ModelForm方式)"""
    if request.method == 'GET':
        form = CaseModelForm()
        return render(request, 'case_add.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = CaseModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        form.save()
        return redirect('/case/list')
    # 如果不满足if判断进入到else返回错误信息
    return render(request, 'case_add.html', {"form": form})


class CaseEditModelForm(forms.ModelForm):
    # 控制字段显示,但是不可编辑
    number = forms.CharField(disabled=True, label="用例编号")
    class Meta:
        model = models.Case
        fields = ["number", "name", "step", "expect", "actual", "priority", "author",  "status", "bug_no"]

        # fields = "__all__"  # 这个表示所有字段
        # exclude = ["bug_no"] #  排除字段

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 循环找到所有插件,添加了class: "from-control"
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

    # 钩子函数进行判重验证,这个名字注意是clean_加字段名
    def clean_number(self):
        # 获取当前编辑那一行的ID,从POST那里获取到了instance
        # print(self.instance.pk)
        tex_number = self.cleaned_data['number']
        exists = models.Case.objects.exclude(id=self.instance.pk).filter(number=tex_number).exists()
        if exists:
            raise ValidationError("用例编号已存在")
        return tex_number


def case_edit(request, nid):
    """编辑用户"""
    # 根据nid去数据库获取所在行数据
    row_object = models.Case.objects.filter(id=nid).first()
    if request.method == 'GET':
        form = CaseEditModelForm(instance=row_object)
        return  render(request, 'case_edit.html', {"form": form})
    # POST 请求提交的数据,数据校验
    form = CaseEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        # 如果数据合法,这里判断的是所有字段不能为空,则存储到数据库
        # models.UserInfo.objects.create(..) 常规存储方式
        # form.instance.字段名=值  # 如果需要存储用户输入之外的值使用这个
        form.save()
        return redirect('/case/list')
        # 如果不满足if判断进入到else返回错误信息
    return render(request, 'case_edit.html', {"form": form})


def case_delete(request, nid):
    """删除用例"""
    # 根据nid去数据库获取所在行数据进行删除
    models.Case.objects.filter(id=nid).delete()
    return redirect('/case/list')

2)修改case_list.html

新增查询条件区域,这里有一个知识点是查询条件保留

 views.py方法返回查询传过来的值,""不输入查询条件就按空查询

{% extends 'layout.html' %}
{% block title %}
    <title>用例列表</title>
{% endblock %}
{% block content %}
    <div class="container">
        <div style="margin-bottom: 10px" class="clearfix">
            <a class="btn btn-success" href="/case/add/">
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
                新建
            </a>

            <div style="float: right;width: 300px">
                <form method="get">
                    <div class="input-group">

                        <input type="text" name="q" class="form-control" placeholder="请输入用例名称">
                        <span class="input-group-btn">
                            <button class="btn btn-default" type="submit">
                                <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
                            </button>
                        </span>

                    </div>
                </form>
            </div>

        </div>

        <div class="bs-example" data-example-id="panel-without-body-with-table">
            <div class="panel panel-default">
                <!-- Default panel contents -->
                <div class="panel-heading">
                    <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
                    用例列表
                </div>

                <!-- Table -->
                <table class="table table-bordered">
                    <thead>
                    <tr>
                        <th>序号</th>
                        <th>用例编号</th>
                        <th>用例名称</th>
                        <th>步骤</th>
                        <th>期望结果</th>
                        <th>实际结果</th>
                        <th>优先级</th>
                        <th>作者</th>
                        <th>状态</th>
                        <th>缺陷编号</th>
                        <th>操作</th>

                    </tr>
                    </thead>
                    <tbody>
                    {% for obj in case_set %}
                        <tr>
                            <th scope="row">{{ obj.id }}</th>
                            <td>{{ obj.number }}</td>
                            <td>{{ obj.name }}</td>
                            <td>{{ obj.step }}</td>
                            <td>{{ obj.expect }}</td>
                            <td>{{ obj.actual|default_if_none:"&nbsp;" }}</td>
                            <td>{{ obj.get_priority_display }}</td>
                            <td>{{ obj.author }}</td>
                            <td>{{ obj.get_status_display }}</td>
                            <td>{{ obj.bug_no|default_if_none:"&nbsp;" }}</td>
                            <td>
                                <a class="btn btn-primary btn-xs" href="/case/{{ obj.id }}/edit/">编辑</a>
                                <a class="btn btn-danger btn-xs" href="/case/{{ obj.id }}/delete/">删除</a>
                            </td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>


    </div>

{% endblock %}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/358729.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年TS4 入门笔记【慕课网imooc】【Vue3+React18 + TS4考勤系统】

目录 安装ts 基础 类型声明和变量声明 类型注解和类型判断 类型分类与联合类型与交叉类型​编辑 never类型与any类型与unknown类型 类型断言与非空断言 数组类型和元祖类型 对象类型与索引签名 函数类型与void类型 函数重载与可调用注解 枚举类型与const枚举 进阶…

机械革命黑苹果改造计划第四番-外接显示器、win时间不正确问题解决

问题 1.无法外接显示器 最大的问题就是目前无法外接显示器&#xff0c;因为机械革命大多数型号笔记本电脑的HDMI、DP接口都是直接物理接在独显上的&#xff0c;内屏用核显外接显示器接独显&#xff0c;英伟达独显也是黑苹果无法驱动的&#xff0c;而且发现机械革命tpyec接口还…

k8s的基础概念

目录 一、k8s概念 1、k8s是什么 2、为什么要用k8s 3、k8s的特性 二、kubernetes集群架构与组件 1、Master组件 1.1、Kube-apiserver 1.2、Kube-controller-manager 1.3、Kube-scheduler 2、配置储存中心 3、Node组件 3.1、Kubelet 3.2、Kube-Proxy 3.3、docker 或…

SAP S/4 HANA 现金流量表

S4 HANA中的现金流量表 引言&#xff1a;在传统SAP ECC中我们实现现金流量表的方式通常是定义一系列和现金流变动相关的原因代码&#xff08;Reason Code&#xff09;&#xff0c;然后在过账凭证里指定对应的Code&#xff0c;最后通过ABAP代码抓取这些数据产生现金流量表。此方…

力扣(LeetCode)417. 太平洋大西洋水流问题(2023.02.19)

有一个 m n 的矩形岛屿&#xff0c;与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界&#xff0c;而 “大西洋” 处于大陆的右边界和下边界。 这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights &#xff0c; heights[r][c]…

【pm2】pm2的安装与基本命令:

文章目录一、安装&#xff1a;二、基本命令&#xff1a;【1】启动命令&#xff1a;pm2 start app.js【2】命令行参数&#xff1a;pm2 start app.js --watch -i max【3】 查看有哪些进程&#xff1a;pm2 list【4】停止命令&#xff1a; pm2 stop app_name | app_id &#xff08;…

el-table 复杂表头行内增删改代码示例

效果如图 <template><div class"app-container"><el-card class"box-card item"><div slot"header" class"clearfix" click"showCondition !showCondition"><span><i class"el-ic…

外籍在读博士|赴新西兰奥克兰大学双院士导师麾下联合培养

N同学来自阿拉伯国家&#xff0c;但本硕博都是在我国某省属高校就读&#xff0c;现为材料学专业一年级博士生。联合培养首选澳洲国家&#xff0c;包括澳大利亚和新西兰&#xff0c;其次是美国&#xff0c;希望在2023年初出国&#xff0c;以完成整个学年的学习计划。在我们的帮助…

Android稳定性系列-01-使用 Address Sanitizer检测原生代码中的内存错误

前言想必大家曾经被各种Native Crash折磨过&#xff0c;本地测试没啥问题&#xff0c;一到线上或者自动化测试就出现各种SIGSEGV、SIGABRT、SIGILL、SIGBUS、SIGFPE异常&#xff0c;而且堆栈还是崩溃到libc.so这种&#xff0c;看起来跟我们的代码没啥关系&#xff0c;关键还不好…

Spark3每个job之间任务间隔过长

公司的跑批引擎从impala改成Spark3已经有一个多月了。 不得不说&#xff0c;跑批稳定了好多。资源控制有相对稳定了很多。Spark3比CDH的hive on spark2.4.0要快不少。AQE和CBO真的挺强的。但是使用中发现了一个很奇怪的事情。这个问题在网上搜过&#xff0c;并没有实际解决。 当…

【机器学习】决策树-ID3算法

1.ID3算法 ID3算法利用信息增益进行特征的选择进行树的构建。信息熵的取值范围为0~1&#xff0c;值越大&#xff0c;越不纯&#xff0c;相反值越小&#xff0c;代表集合纯度越高。信息增益反映的是给定条件后不确定性减少的程度。每一次对决策树进行分叉选取属性的时候&#x…

CANopen概念总结、心得体会

NMT网络管理报文&#xff1a; NMT 主机和 NMT 从机之间通讯的报文就称为 NMT 网络管理报文。常见报文说明&#xff1a; 0101---------------网络报文发送Nmt_Start_Node&#xff0c;让电机进入OP模式(此时还不会发送同步信号) setState(d, Operational)------------------开启…

拳打DALL-E 2脚踢Imagen,谷歌最新Muse模型刷新文本图像合成排行榜

原文链接&#xff1a;https://www.techbeat.net/article-info?id4501 作者&#xff1a;seven_ 论文链接&#xff1a; https://arxiv.org/abs/2301.00704 项目主页&#xff1a; https://muse-model.github.io/ 近期火爆AI社区的文本图像合成模型家族又添新成员了&#xff0c;之…

网络计划--时间参数的计算和优化

根据网络图的基本概念和原则绘制出网络图之后&#xff0c;我们可以计算网络图中有关的时间参数&#xff0c;主要目的是找出关键路线&#xff0c;为网络计划的优化、调整和执行提供明确的时间概念。如下图中从始点①到终点⑧共有4条路线&#xff0c;可以分别计算出每条路线所需的…

基于Hive的河北新冠确诊人数分析系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

通过官网怎么查找联盟申请链接

欢迎关注勤于奋每天12点准时更新国外LEAD相关技术今天还是来聊聊这个问题吧&#xff0c;很多人问我这个问题&#xff0c;我觉得这个都不是啥多难的技术&#xff0c;用点心就能找到。最简单的办法就是通过浏览器去搜索&#xff0c;比如通过google 搜索,就能找到一些信息&#xf…

第三届无线通信AI大赛分享交流会暨颁奖典礼顺利举办,大赛圆满收官

2月16日&#xff0c;第三届无线通信AI大赛分享交流会暨颁奖典礼在北京顺利举行&#xff0c;宣告大赛圆满收官。 分享交流会暨颁奖典礼以线上线下结合的形式展开&#xff0c;邀请无线通信领域的多位专家、学者与「基于AI的信道估计与信道状态信息反馈联合设计」、「基于AI的高精…

将二进制文件作为目标文件中的一个段

将二进制文件作为目标文件中的一个段 python 生成2进制文件 import sysdef testFile(fileName):# --with open(fileName, modewb) as hexFile:bBuf bytes.fromhex("0123456789abcdef")print("bBuf:",bBuf.hex())len hexFile.write(bBuf)print ("l…

Vue3搭建记录

一、初始化项目&#xff1a;项目名称vue3-element-admin npm init vitelatest vue3-element-admin --template vue-ts 二、整合Element-Plus 1.本地安装Element Plus和图标组件 npm install element-plus npm install element-plus/icons-vue 2.全局注册组件 // main.ts imp…

【C#】async关键字修饰后有无await的影响

文章目录测试总结拓展&#xff1a;js的async await问题参考测试 来自微软官网的说法&#xff1a; 异步方法通常包含 await 运算符的一个或多个匹配项&#xff0c;但缺少 await 表达式不会导致编译器错误。 如果异步方法未使用 await 运算符标记悬挂点&#xff0c;则该方法将作…