django项目实战三(django+bootstrap实现增删改查)进阶分页
目录
一、分页
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:" " }}</td><td>{{ obj.get_priority_display }}</td><td>{{ obj.author }}</td><td>{{ obj.get_status_display }}</td><td>{{ obj.bug_no|default_if_none:" " }}</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.UserInfofields = ["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_sizeend = page * page_sizecase_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=5plus = 5# 数据未到达11页(数据量不达标时)if total_count <= 2 * plus + 1:start_page = 1end_page = total_page_countelse:# 当前页< 5(前面的异常考虑)if page <= plus:start_page = 1end_page = 2 * plus + 1else:# 当前页+plus大于总页面(后面的异常考虑)if page + plus > total_page_count:start_page = total_page_count - 2 * plusend_page = total_page_countelse:# 前五页,后五页start_page = page - plusend_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)# 拼接htmlpage_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_numberdef 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.Casefields = ["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_numberdef 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_safeclass 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 = 1self.page = pageself.page_size = page_sizeself.start = (self.page - 1) * self.page_sizeself.end = self.page * self.page_sizeself.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 += 1self.total_page_count = total_page_countself.plus = plusdef html(self):# 计算出,线上当前页的前5页,后5页,plus=5# 数据未到达11页(数据量不达标时)if self.total_page_count <= 2 * self.plus + 1:start_page = 1end_page = self.total_page_countelse:# 当前页< 5(前面的异常考虑)if self.page <= self.plus:start_page = 1end_page = 2 * self.plus + 1else:# 当前页+plus大于总页面(后面的异常考虑)if self.page + self.plus > self.total_page_count:start_page = self.total_page_count - 2 * self.plusend_page = self.total_page_countelse:# 前五页,后五页start_page = self.page - self.plusend_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)# 拼接htmlpage_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.UserInfofields = ["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_datacase_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_numberdef 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.Casefields = ["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_numberdef 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 copyclass 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 = Trueself.query_dict = query_dict# ########################################self.page_param = page_parampage = request.GET.get(self.page_param, "1")if page.isdecimal():page = int(page)else:page = 1self.page = pageself.page_size = page_sizeself.start = (self.page - 1) * self.page_sizeself.end = self.page * self.page_sizeself.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 += 1self.total_page_count = total_page_countself.plus = plusdef html(self):# 计算出,线上当前页的前5页,后5页,plus=5# 数据未到达11页(数据量不达标时)if self.total_page_count <= 2 * self.plus + 1:start_page = 1end_page = self.total_page_countelse:# 当前页< 5(前面的异常考虑)if self.page <= self.plus:start_page = 1end_page = 2 * self.plus + 1else:# 当前页+plus大于总页面(后面的异常考虑)if self.page + self.plus > self.total_page_count:start_page = self.total_page_count - 2 * self.plusend_page = self.total_page_countelse:# 前五页,后五页start_page = self.page - self.plusend_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)# 拼接htmlpage_string = mark_safe("".join(page_str_list))return page_string
四、优化其他查询页面实现分页和查询
将查询条件、分页在用户管理、部门管理实现
五、优化分页显示总页数和总条数
略
相关文章:

django项目实战三(django+bootstrap实现增删改查)进阶分页
目录 一、分页 1、修改case_list.html页面 2、修改views.py的case_list方法(分页未封装) 二、分页封装 1、新建类Pagination 2、修改views.py的case_list方法 三、再优化,实现搜索分页qing情况 四、优化其他查询页面实现分页和查询 五…...

Python 之 Pandas DataFrame 数据类型的简介、创建的列操作
文章目录一、DataFrame 结构简介二、DataFrame 对象创建1. 使用普通列表创建2. 使用嵌套列表创建3 指定数值元素的数据类型为 float4. 字典嵌套列表创建5. 添加自定义的行标签6. 列表嵌套字典创建 DataFrame 对象7. Series 创建 DataFrame 对象三、DataFrame 列操作1. 选取数据…...
华为OD机试真题Python实现【5键键盘的输出】真题+解题思路+代码(20222023)
🔥系列专栏 华为OD机试(Python)真题目录汇总华为OD机试(JAVA)真题目录汇总华为OD机试(C++)真题目录汇总华为OD机试(JavaScript)真题目录汇总文章目录 🔥系列专栏题目输入输出描述:示例1:示例2:解题思路代码实现运行结果:版权说明:题目...

IDEA全家桶式讲解 | IDEA安装、使用、断点调试、Git、插件 (第二篇)
目录 一:JavaEE阶段需要掌握的IDEA技能 1. 配置Tomcat 2. 配置Maven 3. IDEA连接数据库 4. 方便的特殊功能 5. 断点调试(重点) 6. IDEA中常用Git协同开发(重点) 7. 常用插件安装 一:JavaEE阶段需要…...

音视频基础之封装格式与音视频同步
封装格式的概念 封装格式(也叫容器)就是将已经编码压缩好的视频流、音频流及字幕按照一定的方案放到一个文件中,便于播放软件播放。 一般来说,视频文件的后缀名就是它的封装格式。 封装的格式不一样,后缀名也就不一样。 比如&a…...

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

Learning C++ No.11【string类实现】
引言: 北京时间:2023/2/19/8:48,昨天更新了有关进程状态的博客,然后在休息的时候,打开了腾讯视屏,然后看到了了一个电视剧,导致上头,从晚上6点看到了10点,把我宝贵的博客…...

实力见“证”:Tapdata 技术创新与发展潜力广受认可
Tapdata 积极拥抱各种“不确定”,变中求新,只为呈现出更加好用的产品。 而 Tapdata 在专业领域不断深耕,持续打磨产品能力的同时,也收获了诸多来自外界的肯定,从用户到投资人,从生态伙伴到技术媒体以及官方…...

【C++修炼之路】18.map和set
每一个不曾起舞的日子都是对生命的辜负 map和setmap和set一.关联式容器二.set2.1 set的介绍2.2 set的使用1.set的模板参数列表2.set的构造3.set的迭代器4.set修改操作5.bound函数三.multiset四.map3.1 map的介绍3.2 map的使用1.map的模板参数说明2.pair的介绍3.map的[]重载五.m…...

ChatGPT原理与技术演进剖析
—— 要抓住一个风口,你得先了解这个风口的内核究竟是什么。本文作者:黄佳 (著有《零基础学机器学习》《数据分析咖哥十话》) ChatGPT相关文章已经铺天盖地,剖析(现阶段或者只能说揣测)其底层原…...

Retrofit+Hilt后端请求小项目1--项目介绍
简介 本项目根据 youtube 对应教程实现而来 将会对对应代码以及依赖(如 Hilt、retrofit、coil)进行详细的分析与解读,同时缕清项目结构安排 如文章有叙述不清晰的,请直接查看原教程:https://www.youtube.com/watch?…...

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

Structure|Alphafold2在肽结构预测任务上的基准实验
题目:Benchmarking AlphaFold2 on peptide structureprediction 文献来源:2023, Structure 31, 1–9 代码:基准实验,比较了比较多的模型 1.背景介绍 由2-50个氨基酸构成的聚合物可以称为肽。但是关于肽和蛋白质之间的差异还是…...
Simple XML
简介 官网:https://simple.sourceforge.net/home.php Github:https://github.com/ngallagher/simplexml Simple 是用于 Java 的高性能 XML 序列化和配置框架。它的目标是提供一个 XML 框架,使 XML 配置和通信系统的快速开发成为可能。该框架…...

在代码质量和工作效率的矛盾间如何取舍?
这个问题的答案是,在很短的一段时期,编写高质量代码似乎会拖慢我们的进度。与按照头脑中首先闪现的念头编写代码相比,高质量的代码需要更多的思考和努力。但如果我们编写的不仅仅是运行一次就抛之脑后的小程序,而是更有实质性的软…...

rabbitMq安装(小短文)--未完成
rabbitMq是在activeMq的基础上创造的,有前者的功能,比前者强,属于后来居上。系统环境:windows10首先下载相关软件Erlang,因为他是这个语言写的。https://www.erlang.org/downloads然后安装,并且弄到环境变量里验证是否…...

Python调用MMDetection实现AI抠图去背景
这篇文章的内容是以 《使用MMDetection进行目标检测、实例和全景分割》 为基础,需要安装好 MMDetection 的运行环境,同时完成目标检测、实例分割和全景分割的功能实践,之后再看下面的内容。 想要实现AI抠图去背景的需求,我们需要…...

Java代码使用最小二乘法实现线性回归预测
最小二乘法简介最小二乘法是一种在误差估计、不确定度、系统辨识及预测、预报等数据处理诸多学科领域得到广泛应用的数学工具。它通过最小化误差(真实目标对象与拟合目标对象的差)的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数…...

linux-rockchip-音频相关
一、查看当前配置声卡状态 cat /proc/asound/cards二、查看当前声卡工作状态 声卡分两种通道,一种是Capture、一种是Playback。Capture是输入通道,Playback是输出通道。例如pcm0p属于声卡输出通道,pcm0c属于声卡输入通道。 ls /proc/asoun…...

Android Handler的内存抖动以及子线程创建Handler
一、介绍 Handler,作为一个在主线程存活的消息分发工具,在App开发过程使用频率很高,也是面试问的比较多的。 面试常见的比如:子线程如何创建?Handler的机制是什么?内存抖动等,接下来我们会针对H…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...

若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...

李沐--动手学深度学习--GRU
1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...