django项目实战三(django+bootstrap实现增删改查)进阶分页

news2024/11/14 14:27:58

目录

一、分页

 1、修改case_list.html页面

2、修改views.py的case_list方法(分页未封装)

二、分页封装

1、新建类Pagination

2、修改views.py的case_list方法

三、再优化,实现搜索+分页qing情况

四、优化其他查询页面实现分页和查询

五、优化分页显示总页数和总条数


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

知识点:

        分页的封装

        

一、分页

 1、修改case_list.html页面

  

{% 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="请输入用例名称"
                               value="{{ search_data }}">
                        <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>


        <ul class="pagination">
            {{ page_string }}          
        </ul>


    </div>

{% endblock %}

2、修改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
from django.utils.safestring import mark_safe
# 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 = {}
    # 获取浏览器传过来的值
    search_data = request.GET.get('q', "")
    if search_data:
        data_dict["name__contains"] = search_data

    # 根据用户想要的访问页码,计算出起止位置
    page = int(request.GET.get('page', 1))
    page_size = 10  # 每页显示数据量
    start = (page - 1) * page_size
    end = page * page_size

    case_set = models.Case.objects.filter(**data_dict).order_by('-id')[start:end]
    # 数据总条数
    total_count = models.Case.objects.filter(**data_dict).order_by('-id').count()
    total_page_count, div = divmod(total_count, page_size)
    if div:
        total_page_count += 1
    # 计算出,线上当前页的前5页,后5页,plus=5
    plus = 5
    # 数据未到达11页(数据量不达标时)
    if total_count <= 2 * plus + 1:
        start_page = 1
        end_page = total_page_count
    else:
        # 当前页< 5(前面的异常考虑)
        if page <= plus:
            start_page = 1
            end_page = 2 * plus + 1
        else:
            # 当前页+plus大于总页面(后面的异常考虑)
            if page + plus  > total_page_count:
                start_page = total_page_count - 2 * plus
                end_page = total_page_count
            else:
                # 前五页,后五页
                start_page = page - plus
                end_page = page + plus
    # 页码
    page_str_list = []

    # 首页
    page_str_list.append('<li><a href="?page={}">首页</a></li>'.format(1))
    # 上一页
    if page > 1:
        prev = '<li><a href="?page={}">上一页</a></li>'.format(page-1)
    else:
        prev = '<li><a href="?page={}">上一页</a></li>'.format(1)
    page_str_list.append(prev)
    # 页面
    for i in range(start_page, end_page + 1):
        if i == page:
            ele = '<li class="active"><a href="?page={}">{}</a></li>'.format(i, i)
        else:
            ele = '<li><a href="?page={}">{}</a></li>'.format(i, i)

        page_str_list.append(ele)
    # 下一页
    if page < total_page_count:
        prev = '<li><a href="?page={}">下一页</a></li>'.format(page + 1)
    else:
        prev = '<li><a href="?page={}">下一页</a></li>'.format(total_page_count)
    page_str_list.append(prev)

    # 尾页
    page_str_list.append('<li><a href="?page={}">尾页</a></li>'.format(total_page_count))
    # 跳转
    search_string = """
    <li>
        <form style="float: left;margin-left: -1px" method="get">
            <input name="page"
                   style="position: relative;float: left;display: inline-block;width: 80px;border-radius: 0"
                   type="text"  class="form-control" placeholder="页码">
                <button style="border-radius: 0" class="btn btn-default" type="submit">跳转</button>
            </span>
        </form>
    </li>
    """
    page_str_list.append(search_string)
    # 拼接html
    page_string = mark_safe("".join(page_str_list))

    return render(request, 'case_list.html', {"case_set": case_set, "search_data": search_data, "page_string": page_string})



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')

二、分页封装

1、新建类Pagination

在应用下新建文件夹utils,然后在下面创建pagination.py模块 

# -*- coding: utf-8 -*-
# @Time    : 2023/2/20 15:24
# @Author  : caicloud
# @File    : pagination.py
# @Software: PyCharm
# @Describe: 自定义分页组件
from django.utils.safestring import mark_safe

class Pagination(object):
    def __init__(self, request, queryset, page_size=10, page_param='page', plus=5):
        page = request.GET.get(page_param, "1")
        if page.isdecimal():
            page = int(page)
        else:
            page = 1
        self.page = page
        self.page_size = page_size
        self.start = (self.page - 1) * self.page_size
        self.end = self.page * self.page_size
        self.page_queryset = queryset[self.start: self.end]
        # 数据总条数
        total_count = queryset.count()
        total_page_count, div = divmod(total_count, page_size)
        if div:
            total_page_count += 1
        self.total_page_count = total_page_count
        self.plus = plus


    def html(self):
        # 计算出,线上当前页的前5页,后5页,plus=5
        # 数据未到达11页(数据量不达标时)
        if self.total_page_count <= 2 * self.plus + 1:
            start_page = 1
            end_page = self.total_page_count
        else:
            # 当前页< 5(前面的异常考虑)
            if self.page <= self.plus:
                start_page = 1
                end_page = 2 * self.plus + 1
            else:
                # 当前页+plus大于总页面(后面的异常考虑)
                if self.page + self.plus > self.total_page_count:
                    start_page = self.total_page_count - 2 * self.plus
                    end_page = self.total_page_count
                else:
                    # 前五页,后五页
                    start_page = self.page - self.plus
                    end_page = self.page + self.plus
        # 页码
        page_str_list = []
        # 首页
        page_str_list.append('<li><a href="?page={}">首页</a></li>'.format(1))
        # 上一页
        if self.page > 1:
            prev = '<li><a href="?page={}">上一页</a></li>'.format(self.page - 1)
        else:
            prev = '<li><a href="?page={}">上一页</a></li>'.format(1)
        page_str_list.append(prev)
        # 页面
        for i in range(start_page, end_page + 1):
            if i == self.page:
                ele = '<li class="active"><a href="?page={}">{}</a></li>'.format(i, i)
            else:
                ele = '<li><a href="?page={}">{}</a></li>'.format(i, i)

            page_str_list.append(ele)
        # 下一页
        if self.page < self.total_page_count:
            prev = '<li><a href="?page={}">下一页</a></li>'.format(self.page + 1)
        else:
            prev = '<li><a href="?page={}">下一页</a></li>'.format(self.total_page_count)
        page_str_list.append(prev)

        # 尾页
        page_str_list.append('<li><a href="?page={}">尾页</a></li>'.format(self.total_page_count))
        # 跳转
        search_string = """
            <li>
                <form style="float: left;margin-left: -1px" method="get">
                    <input name="page"
                           style="position: relative;float: left;display: inline-block;width: 80px;border-radius: 0"
                           type="text"  class="form-control" placeholder="页码">
                        <button style="border-radius: 0" class="btn btn-default" type="submit">跳转</button>
                    </span>
                </form>
            </li>
            """
        page_str_list.append(search_string)
        # 拼接html
        page_string = mark_safe("".join(page_str_list))
        return page_string

2、修改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
from TestManagementSystem.utils.pagination import Pagination
# 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 = {}
    # 获取浏览器传过来的值
    search_data = request.GET.get('q', "")
    if search_data:
        data_dict["name__contains"] = search_data
    case_set = models.Case.objects.filter(**data_dict).order_by('-id')
    # 实例化封装的分页
    page_object = Pagination(request, case_set)
    context = {
        "search_data": search_data,  # 查询
        "case_set": page_object.page_queryset,  # 分完页的数据
        "page_string": page_object.html()  # 页码
    }
    return render(request, 'case_list.html', context)



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')

三、再优化,实现搜索+分页qing情况

知识点,点击分页时保留原来的查询条件

# -*- coding: utf-8 -*-
# @Time    : 2023/2/20 15:24
# @Author  : caicloud
# @File    : pagination.py
# @Software: PyCharm
# @Describe: 自定义分页组件
"""
这个翻页组件的使用说明(视图函数中):
def case_list(request):
    # 第一步查询数据
    case_set = models.Case.objects.all()
    # 第二步实例化封装的分页对象
    page_object = Pagination(request, case_set)
    context = {
        "case_set": page_object.page_queryset,  # 分完页的数据
        "page_string": page_object.html()  # 页码
    }
    return render(request, 'case_list.html', context)

html页面:
        <ul class="pagination">
            {{ page_string }}
        </ul>

"""
from django.utils.safestring import mark_safe
import copy

class Pagination(object):
    def __init__(self, request, queryset, page_size=10, page_param='page', plus=5):
        """

        :param request: 请求对象
        :param queryset: 查询符合条件的数据,根据这个数据进行分页处理
        :param page_size: 每页显示多少条数据
        :param page_param:在url中传递的获取分页的参数,例如/case/list/?page=5
        :param plus:显示当前页的前plus页 或后 plus页
        """
        # 以下是为了解决查询翻页查询条件保留的问题
        query_dict = copy.deepcopy(request.GET)
        query_dict._mutable = True
        self.query_dict = query_dict
        # ########################################
        self.page_param = page_param
        page = request.GET.get(self.page_param, "1")
        if page.isdecimal():
            page = int(page)
        else:
            page = 1
        self.page = page
        self.page_size = page_size
        self.start = (self.page - 1) * self.page_size
        self.end = self.page * self.page_size
        self.page_queryset = queryset[self.start: self.end]
        # 数据总条数
        total_count = queryset.count()
        total_page_count, div = divmod(total_count, page_size)
        if div:
            total_page_count += 1
        self.total_page_count = total_page_count

        self.plus = plus


    def html(self):
        # 计算出,线上当前页的前5页,后5页,plus=5
        # 数据未到达11页(数据量不达标时)
        if self.total_page_count <= 2 * self.plus + 1:
            start_page = 1
            end_page = self.total_page_count
        else:
            # 当前页< 5(前面的异常考虑)
            if self.page <= self.plus:
                start_page = 1
                end_page = 2 * self.plus + 1
            else:
                # 当前页+plus大于总页面(后面的异常考虑)
                if self.page + self.plus > self.total_page_count:
                    start_page = self.total_page_count - 2 * self.plus
                    end_page = self.total_page_count
                else:
                    # 前五页,后五页
                    start_page = self.page - self.plus
                    end_page = self.page + self.plus

        # 页码
        page_str_list = []

        self.query_dict.setlist(self.page_param, [1])
        # 首页
        page_str_list.append('<li><a href="?{}">首页</a></li>'.format(self.query_dict.urlencode()))
        # 上一页
        if self.page > 1:
            self.query_dict.setlist(self.page_param, [self.page - 1])
            prev = '<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode())
        else:
            self.query_dict.setlist(self.page_param, [1])
            prev = '<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode())
        page_str_list.append(prev)
        # 页面
        for i in range(start_page, end_page + 1):
            self.query_dict.setlist(self.page_param, [i])
            if i == self.page:
                ele = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
            else:
                ele = '<li><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)

            page_str_list.append(ele)
        # 下一页
        if self.page < self.total_page_count:
            self.query_dict.setlist(self.page_param, [self.page + 1])
            prev = '<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode())
        else:
            self.query_dict.setlist(self.page_param, [self.total_page_count])
            prev = '<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode())
        page_str_list.append(prev)

        # 尾页
        self.query_dict.setlist(self.page_param, [self.total_page_count])
        page_str_list.append('<li><a href="?{}">尾页</a></li>'.format(self.query_dict.urlencode()))
        # 跳转
        search_string = """
            <li>
                <form style="float: left;margin-left: -1px" method="get">
                    <input name="page"
                           style="position: relative;float: left;display: inline-block;width: 80px;border-radius: 0"
                           type="text"  class="form-control" placeholder="页码">
                        <button style="border-radius: 0" class="btn btn-default" type="submit">跳转</button>
                    </span>
                </form>
            </li>
            """
        page_str_list.append(search_string)
        # 拼接html
        page_string = mark_safe("".join(page_str_list))
        return page_string

四、优化其他查询页面实现分页和查询

将查询条件、分页在用户管理、部门管理实现

 

五、优化分页显示总页数和总条数

 

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

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

相关文章

如何寻找SAP中的增强

文章目录0 简介1 寻找一代增强2 寻找二代增强2.2 在包里也可以看到2.3 在出口对象里输入包的名字也可以找到2.4 通过以下函数可以发现已有的增强2.5 也可以在cmod里直接找2.6 总结3 寻找第三代增强0 简介 在SAP中&#xff0c;对原代码的修改最不容易的是找增强&#xff0c;以下…

Springboot 整合 分布式定时任务 XXL-JOB

起因 恰逢周末&#xff0c; 最近公司接入了分布式定时任务&#xff0c;我是负责接入这块的&#xff0c;正好在网上想起了之前看过的分布式任务的文章&#xff0c;然后学习一下 各路框架发现看了很多框架比如 elasticjob 跟xxl-job不同的是&#xff0c;elasticjob是采用zookeepe…

Cesium 卫星轨迹、卫星通信、卫星过境,模拟数据传输。

起因&#xff1a;看了cesium官网卫星通信示例发现只有cmzl版本的&#xff0c;决定自己动手写一个。欢迎大家一起探讨&#xff0c;评论留言。 效果 全部代码在最后 起步 寻找卫星轨迹数据&#xff0c;在网站space-track上找的&#xff0c;自己注册账号QQ邮箱即可。 卫星轨道类…

stm32f407探索者开发板(十六)——串行通信原理讲解-UART

文章目录一、串口通信接口背景知识1.1 处理器与外部设备通信的两种方式1.2 按照数据传送方向1.3 是否带有时钟信号1.4 常见的串行通信接口二、STM32F4串口通信基础2.1 STM32的串口通信接口2.2 UART异步通信方式引脚连接方法2.3 UART异步通信方式引脚(STM32F407ZGT6)2.4 UART异步…

模拟物流快递系统程序设计-课后程序(JAVA基础案例教程-黑马程序员编著-第四章-课后作业)

【案例4-8】模拟物流快递系统程序设计 欢迎点赞收藏关注 【案例介绍】 案例描述 网购已成为人们生活的重要组成部分&#xff0c;当人们在购物网站中下订单后&#xff0c;订单中的货物就会在经过一系列的流程后&#xff0c;送到客户的手中。而在送货期间&#xff0c;物流管理…

实际项目角度优化App性能

前言&#xff1a;前年替公司实现了一个在线检疫App&#xff0c;接下来一年时不时收到该App的需求功能迭代&#xff0c;部分线下问题跟进。随着新冠疫情防控政策放开&#xff0c;该项目也是下线了。 从技术角度来看&#xff0c;有自己的独特技术处理特点。下面我想记录一下该App…

c++动态内存分布以及和C语言的比较

文章目录 前言一.c/c内存分布 C语言的动态内存管理方式 C内存管理方式 operator new和operator delete函数 malloc/free和new/delete的区别 定位new 内存泄漏的危害总结前言 c是在c的基础上开发出来的&#xff0c;所以关于内存管理这一方面是兼容c的&…

02- OpenCV绘制图形及图像算术变换 (OpenCV基础) (机器视觉)

知识重点 OpenCV用的最多的色彩空间是HSV. 方便OpenCV做图像处理img2 img.view() # 浅拷贝img3 img.copy() # 深拷贝split(mat) 分割图像的通道: b, g, r cv2.split(img) # b, g, r 都是数组merge((ch1, ch2, ch3)) 融合多个通道cvtColor(img, colorspace): 颜…

Centos7系统编译Hadoop3.3.4

1、背景 最近在学习hadoop&#xff0c;此篇文章简单记录一下通过源码来编译hadoop。为什么要重新编译hadoop源码&#xff0c;是因为为了匹配不同操作系统的本地库环境。 2、编译源码 2.1 下载并解压源码 [roothadoop01 ~]# mkdir /opt/hadoop [roothadoop01 ~]# cd /opt/had…

运动蓝牙耳机哪个牌子好性价比高、性价比高的运动蓝牙耳机推荐

如今耳机是我们生活中很常见的数码产品了&#xff0c;在街上看到跑步、骑行&#xff0c;室内健身房&#xff0c;都能看到大家人手一副耳机&#xff0c;运动耳机已经成为很多人的运动必备品&#xff0c;因大众佩戴耳机的种类和风格有所不同&#xff0c;这也造就了市场上琳琅满目…

RT-Thread SPI使用教程

RT-Thread SPI 使用教程 实验环境使用的是正点原子的潘多拉开发板。 SPI从机设备使用的是BMP280温湿度大气压传感器。 使用RT-Thread Studio搭建基础功能。 1. 创建工程 使用RT-Thread Studio IDE创建芯片级的工程。创建完成后&#xff0c;可以直接编译下载进行测试。 2.…

电源电路设计(一)(文末有易灵思核心板及下载线)

现在随着电子技术的高速发展&#xff0c;电子系统的应用领域也变得越来越广泛&#xff0c;电子设备的种类也在逐渐的不断更新、不断增多&#xff0c;电子设备与人们日常的工作、生活的关系也是日益密切。任何的电子设备都离不开安全有效的电源&#xff0c;电源是一切电力电子设…

后来我放弃了Obsidian手机端,改用Flomo | Obsidian实践

Obsidian在本地管理笔记文件的方式是把双刃剑。一方面&#xff0c;用户自行管理笔记文件可以获得更多的安全感&#xff0c;不用担心会出现“平台挂掉了&#xff0c;笔记丢失”的情况&#xff1b;另一方面&#xff0c;免费版Obsidian无法进行多终端笔记同步的问题又常常遭人诟病…

c++11 标准模板(STL)(std::unordered_set)(三)

定义于头文件 <unordered_set> template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templ…

wafw00f工具

wafw00f Web应用程序防火墙指纹识别工具 github地址&#xff1a;https://github.com/EnableSecurity/wafw00f 安装环境&#xff1a;python3环境 —>使用 pip install wafw00f 进行安装 安装成功后目录&#xff1a;python安装目录中的Lib\site-packages\wafw00f 本机为&a…

Hadoop - HDFS

Hadoop - HDFS 1. HDFS介绍 1.1 定义 HDFS是一个分布式文件系统&#xff0c;适合一次写入&#xff0c;多次读出的场景 数据可以保存在多个副本当中&#xff0c;可以通过增加副本的数量来增加容错 不适用于低延时数据访问的场景 不能高效的对小文件进行存储 因为会占用Na…

MySQL —— 内外连接

目录 表的内外连接 一、内连接 二、外连接 1. 左外连接 2. 右外连接 表的内外连接 表的连接分为内连和外连 一、内连接 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选&#xff0c;我们前面博客中的查询都是内连接&#xff0c;也是在开发过程中使用的最多…

为GDI+增加类似QPainter的Save和Restore功能

文章目录一、实现思路1、功能设计2、大体实现思路二、代码实现1、实现IList2、实现功能函数3、调用测试原文出处&#xff1a; https://blog.csdn.net/haigear/article/details/129116662在使用GDI绘图时&#xff0c;不得不说QT中的QPainter有些功能是让人羡慕的&#xff0c;比如…

【Java基础】泛型

泛型 generic 泛型的好处 编译器自动检查&#xff0c;减少了出错减少了转换次数&#xff0c;提高效率不再提示编译警告使程序员能够实现通用算法 定义 接口和类&#xff0c;方法都可以定义泛型 //泛型类会被在创建实例的时候被确定 // 泛型可以有多个 class Person<T,…

3分钟带您快速了解HIL测试及其架构

什么是HIL测试硬件在环&#xff08;HIL&#xff09;仿真是一种用于测试导航系统的技术&#xff0c;其中测试前并不知道车辆轨迹。在这种情况下&#xff0c;车辆轨迹被实时馈送到GNSS模拟器。HIL可用于复杂实时系统的开发和测试&#xff0c;如卫星控制系统、军事战术导弹、飞机飞…