Python-django 自定义模块开发-列表展示
第四章 Django 自定义模块-年级模块开发过程
前言
这一系列文章是通过一个简单的学校项目进行演示的,项目中遇到的问题将一一记录下来,仅供参考。
[En]
This series of articles is demonstrated by a simple school project, and the problems encountered in the project will be recorded one by one for reference only.
此处学习版本 python3.8 django 4.0.6 bootstrap3 开发工具 VSCODE
一、创建静态页面-年级首页
对应的路径:school\school_web_grade\templates\grade\grade_index.html
{% load i18n static %}
<html>
<head>
<title>年级管理title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1/css/bootstrap.min.css' %}" />
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1/css/bootstrap-theme.min.css' %}" />
<script src="{% static 'js/jquery-3.2.1/jquery.min.js' %}">script>
<script src="{% static 'js/popper-1.15.0/umd/popper.min.js' %}">script>
<script src="{% static 'bootstrap-3.4.1/js/bootstrap.min.js' %}">script>
<style type="text/css">
style>
head>
<body>
<div class="container-fluid">
<div class="row">
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="{% url 'school_web_grade:index'%}" style="padding-top:5px;">
<img alt="Brand" src="{% static 'images/ico.png' %}" />
a>
<a class="navbar-brand" href="{% url 'school_web_grade:index'%}">陕西家里蹲大学师生信息管理系统a>
div>
<div>
<ul class="nav navbar-nav" id="ul_menu_top">
<li><a href="{% url 'school_web_grade:gradeIndex' pageIndex=1 %}">年级管理a>li>
<li><a href="#">学科管理a>li>
<li><a href="#">教师管理a>li>
<li><a href="#">班级管理a>li>
<li><a href="#">学生管理a>li>
ul>
div>
<ul class="nav navbar-nav navbar-right">
<li><a href="#"><span class="glyphicon glyphicon-user">span> 注册a>li>
<li><a href="#"><span class="glyphicon glyphicon-log-in">span> 登录a>li>
<li>
<a href="javascript:void(0)" onclick="openModalWindow()">
<span class="glyphicon glyphicon-off">span> 退出
a>
li>
ul>
div>
nav>
div>
<div class="row" style="padding-top: 50px;padding-bottom: 50px;">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title "><span class=" glyphicon glyphicon-search">span>年级管理查询条件h3>
div>
<div class="panel-body">
<form class="form-inline" id="gradeForm" name="gradeForm" action="{% url 'school_web_grade:gradeIndex' pageIndex=1 %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="grade_name_id">年级名称:label>
<input type="text" name="grade_name" class="form-control" id="grade_name_id" value="{{grade_name}}" placeholder="请输入年级名称" />
div>
<div class="form-group pull-right">
<button type="submit" class="btn btn-success">查询button>
<a href="javascript:void(0);" onclick="addGrade()" class="btn btn-info" role="button">新增a>
<a href="javascript:void(0);" onclick="openModalWindow()" class="btn btn-info" role="button">弹出框a>
div>
form>
div>
div>
<div class="panel panel-info">
<div class="panel-heading"><span class="glyphicon glyphicon-list">span>数据展示div>
<div class="panel-body">
{% block content %}
<div class="row ">
<table class="table table-striped table-bordered text-center">
<thead>
<tr>
<th class="text-center">当页索引th>
<th class="text-center">编号th>
<th class="text-center">年级名称th>
<th class="text-center">创建日期th>
<th class="text-center">修改日期th>
<th class="text-center">操作th>
tr>
thead>
<tbody>
{% for grade in gradeList %}
<tr class="{% cycle 'info' 'success' as rowcolors %}">
<td>{{ forloop.counter }}td>
<td>{{ grade.grade_id }}td>
<td>{{ grade.grade_name }}td>
<td>{{ grade.grade_create_date|date:"Y-m-d H:i:s" }}td>
<td>{{ grade.grade_update_date|date:"SHORT_DATE_FORMAT" }}td>
<td>
<button type="button" class="btn btn-info btn-xs" data-url="{% url 'school_web_grade:gradeDetail' grade.grade_id %}"
onclick="detailGrade(this)">
<span class="glyphicon glyphicon-zoom-in">span>详情
button>
<button type="button" class="btn btn-warning btn-xs" data-url="{% url 'school_web_grade:loadGradeEdit' grade.grade_id %}" onclick="editGrade(this)" >
<span class="glyphicon glyphicon-pencil">span>修改
button>
<button type="button" class="btn btn-danger btn-xs" data-url="{% url 'school_web_grade:gradeDelete' grade.grade_id %}" onclick="deleteGrade(this)" >
<span class="glyphicon glyphicon-remove">span>删除
button>
td>
tr>
{% empty %}
<tr class="success">
<td colspan="6">没有查询到数据...td>
tr>
{% endfor %}
tbody>
table>
div>
<div class="row">
<nav aria-label="Page navigation" class="text-center">
<ul class="pagination">
{% if currentGradePage.has_previous == True %}
<li><a href="javascript:void(0);" data-url="{% url 'school_web_grade:gradeIndex' pageIndex=1 %}" aria-label="Previous"><span aria-hidden="true">首页span>a>li>
<li><a href="javascript:void(0);" data-url="{% url 'school_web_grade:gradeIndex' pageIndex=pageIndex|add:-1 %}" aria-label="Previous"><span aria-hidden="true">上一页span>a>li>
{% else %}
<li class="disabled"><span aria-hidden="true">首页span>li>
<li class="disabled"><span aria-hidden="true">上一页span>li>
{% endif%}
<li class="active"><span aria-hidden="true">{{ pageIndex}}span>li>
{% if currentGradePage.has_next == True %}
<li><a href="javascript:void(0);" data-url="{% url 'school_web_grade:gradeIndex' pageIndex|add:1 %}" aria-label="Next"><span aria-hidden="true">下一页span>a>li>
<li><a href="javascript:void(0);" data-url="{% url 'school_web_grade:gradeIndex' pageIndex=currentGradePage.paginator.num_pages %}" aria-label="Next"><span aria-hidden="true">尾页span>a>li>
{% else %}
<li class="disabled"><span aria-hidden="true">下一页span>li>
<li class="disabled"><span aria-hidden="true">尾页span>li>
{% endif %}
<li class="disabled"><span aria-hidden="true">共 {{currentGradePage.paginator.count}} 条span>li>
ul>
nav>
div>
{% endblock %}
div>
div>
div>
<div class="row navbar navbar-default navbar-fixed-bottom" style="text-align: center; height: 40px;">
<div class="bg-success" style="height: 100% ;padding-top: 15px;">
版权所有@copyRight 2013-2022 口袋里的小龙 开发框架 python3.8 bootstrap-3 Django4
div>
div>
div>
<div class="modal fade " id="modalWindowDiv" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×button>
<h4 class="modal-title" id="myModalLabel">
模态框(Modal)标题
h4>
div>
<div class="modal-body">
按下 ESC 按钮退出。
<form>
<div class="form-group">
<label for="recipient-name" class="control-label">Recipient:label>
<input type="text" class="form-control" id="recipient-name">
div>
<div class="form-group">
<label for="message-text" class="control-label">Message:label>
<textarea class="form-control" id="message-text">textarea>
div>
form>
div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭
button>
<button type="button" class="btn btn-primary">
提交更改
button>
div>
div>
div>
div>
<script type="text/javascript">
$(document).ready(function () {
// 在这里写你的代码...
$('#showDetail').modal('hide')
//菜单点击事件
$("#ul_menu_top li").click(function () {
//清除样式
$("#ul_menu_top li").removeClass("active");
//设置选中颜色
$(this).addClass("active");
console.log($(this));
});
//表单提交
$(".pagination li a").click(function(){
var data_url = $(this).attr("data-url");
$("#gradeForm").attr("action",data_url);
$("#gradeForm").submit()
});
// hide 方法调用之后立即触发该事件。
$('#modalWindowDiv').on('hidden.bs.modal', function (e) {
// do something...
console.log("hide 方法调用之后立即触发该事件。");
});
//从远端的数据源加载完数据之后触发该事件
$('#modalWindowDiv').on('loaded.bs.modal', function (e) {
// do something...
console.log("从远端的数据源加载完数据之后触发该事件");
});
//show 方法调用之后立即触发该事件。如果是通过点击某个作为触发器的元素,则此元素可以通过事件的 relatedTarget 属性进行访问。
$('#modalWindowDiv').on('show.bs.modal', function (e) {
// do something...
console.log("show 方法调用之后立即触发该事件");
});
//此事件在模态框已经显示出来(并且同时在 CSS 过渡效果完成)之后被触发。如果是通过点击某个作为触发器的元素,则此元素可以通过事件的 relatedTarget 属性进行访问。
$('#modalWindowDiv').on('shown.bs.modal', function (e) {
// do something...
console.log("此事件在模态框已经显示出来(并且同时在 CSS 过渡效果完成)之后被触发");
});
});
/**
* 模态窗口打开的方法
*/
function openModalWindow() {
//打开模态窗口的方法 手动打开模态框。在模态框显示之前返回到主调函数中
$('#modalWindowDiv').modal('show');
//手动隐藏模态框。在模态框隐藏之前返回到主调函数中
// $('#modalWindowDiv').modal('hide')
}
//添加
function addGrade() {
window.open("{% url 'school_web_grade:gradeAdd' %}");
}
//详情
function detailGrade(_this) {
console.log($(_this).attr("data-url"));
var url = $(_this).attr("data-url");
window.open(url);
}
/**
* 表单提交
*/
function deleteGrade(_this) {
console.log($(_this).attr("data-url"));
var url = $(_this).attr("data-url");
$("#gradeForm").attr("action",url);
$("#gradeForm").submit();
// window.open(url);
}
//修改
function editGrade(_this) {
console.log($(_this).attr("data-url"));
var url = $(_this).attr("data-url");
window.open(url);
}
script>
body>
html>
先创建页面 我再解释 其中的用法
1.指定国际化
{% load i18n static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1/css/bootstrap.min.css' %}" />
2.指定静态文件引用地址{% static ” %} 固定写法
{% static 'bootstrap-3.4.1/css/bootstrap.min.css' %}
<a class="navbar-brand" href="{% url 'school_web_grade:index'%}">陕西家里蹲大学师生信息管理系统a>
3.对应的url请求写法
{% url 'school_web_grade:index'%}其中 {% url 'x:y'%} 为固定写法 "x:y"号中是对应的模块:对应的方法名
4.对应url请求参数
<li><a href="{% url 'school_web_grade:gradeIndex' pageIndex=1 %}">年级管理a>li>
参数的写法是 在请求的url 后面输写 可以写 pageIndex=1 也可以写 1 也可以是个变量 pageIndex
5.数据的展示
<tbody>
{% for grade in gradeList %}
<tr class="{% cycle 'info' 'success' as rowcolors %}">
<td>{{ forloop.counter }}td>
<td>{{ grade.grade_id }}td>
<td>{{ grade.grade_name }}td>
<td>{{ grade.grade_create_date|date:"Y-m-d H:i:s" }}td>
<td>{{ grade.grade_update_date|date:"SHORT_DATE_FORMAT" }}td>
<td>
<button type="button" class="btn btn-info btn-xs" data-url=""
onclick="detailGrade(this)">
<span class="glyphicon glyphicon-zoom-in">span>详情
button>
<button type="button" class="btn btn-warning btn-xs" data-url="" onclick="editGrade(this)" >
<span class="glyphicon glyphicon-pencil">span>修改
button>
<button type="button" class="btn btn-danger btn-xs" data-url="" onclick="deleteGrade(this)" >
<span class="glyphicon glyphicon-remove">span>删除
button>
td>
tr>
{% empty %}
<tr class="success">
<td colspan="6">没有查询到数据...td>
tr>
{% endfor %}
tbody>
二、后端代码编写
1.创建实体类 model.py
from django.db import models'''模型定义类'''# Create your models here.'''年级类'''class SchoolGrade(models.Model): ''' erbose_name: str | None = ..., 备注字段名 name: str | None = ..., primary_key: bool = ..., 是否主键 如果设置为 True ,将该字段设置为该模型的主键 max_length: int | None = ..., 最大长度 unique: bool = ..., 是否唯一 blank: bool = ..., 是否为空 null: bool = ...,是否为null db_index: bool = ..., 数据索引 rel: ForeignObjectRel | None = ..., default: Any = ..., 默认值 editable: bool = ..., serialize: bool = ..., 是否序列化 unique_for_date: str | None = ..., 唯一日期 unique_for_month: str | None = ..., 唯一月 unique_for_year: str | None = ..., 唯一年 choices: _FieldChoices | None = ..., help_text: str = ..., 这个字段设置后 随 表单一起显示 db_column: str | None = ..., 数据库列 db_tablespace: str | None = ..., 数据库表空间 auto_created: bool = ..., validators: Iterable[_ValidatorCallable] = ..., error_messages: _ErrorMessagesT | None = ... ''' ## 自动生成值得列 如果不设置 primary_key 则会自动生成一个 id 字段 添加到此模型中作为主键自动生成 grade_id = models.BigAutoField(unique=True,serialize=True,primary_key=True,null=False,blank=False,verbose_name="年级表主键") ## 设置年级名称 max_length 最大长度为500 grade_name = models.CharField(max_length=500,verbose_name="年级名称") ## 设置创建时间 grade_create_date = models.DateTimeField(auto_now_add=True,verbose_name="创建时间") ## 设置修改时间 grade_update_date = models.DateTimeField(auto_now_add=True,verbose_name="修改时间")
2.生成数据库表
执行命令:
python .\manage.py makemigrations school_web_gradepython .\manage.py migrate
3.创建业务调用类 views.py
该方法中有一些参数的说明和用法。你可以自己试一试。
[En]
There are descriptions and usage of some parameters in the method. You can try it yourself.
import datetimefrom django.shortcuts import redirect, renderfrom django.views import generic## python 分页from django.core.paginator import Paginator## 引入 年级模型from .models import SchoolGrade# Create your views here.## 调用视图的方法类'''通用视图类 默认主页'''class IndexView(generic.ListView): ## 调用的视图 template_name="index.html" ## 此方法必须有 返回None 都可以 def get_queryset(self): return None'''方法实现'''def index(request): return render(request=request,template_name="index.html")'''年级管理'''## 年级首页def gradeIndex(request,pageIndex): page_index = pageIndex print(page_index) object_list = [] grade_name = "" if request.method == "POST": ## 获取数据的方法 grade_name = request.POST.get("grade_name") print(grade_name) ## 修改时间 # grade_update_date = datetime.datetime.now() ## __contains like 查询 object_list = SchoolGrade.objects.filter(grade_name__contains=grade_name).order_by("grade_create_date") else: ## 查询年级数据 object_list = SchoolGrade.objects.order_by("grade_create_date") # ## 获取总行数 # count = SchoolGrade.objects.order_by("grade_create_date").count() # print("获取总行数",count) ''' object_list: _SupportsPagination, 数据列表 per_page: int | str, 每页显示的条数 orphans: int = ..., 可选的。当你不希望最后一页的项目数量很少时,使用这个选项。如果最后一页的项目数量通常小于或等于 orphans,那么这些项目将被添加到前一页(成为最后一页),而不是让这些项目单独留在一页上。例如,如果有 23 个条目,per_page=10,orphans=3,则会有两页;第一页有 10 个条目,第二页(也是最后一页)有 13 个条目。orphans 默认为 0,这意味着页面永远不会合并,最后一页可能只有一个项目。 allow_empty_first_page: bool = ... 是否允许页面为空 ''' ## 每页显示的条数 必要的。一个页面中包含的最大项目数 per_page = 2 ## 可选的。是否允许第一页为空。 如果 False 并且 object_list 是空的,则会出现 EmptyPage 错误 allow_empty_first_page = True paginator = Paginator(object_list=object_list,per_page=per_page,allow_empty_first_page=True) # print("paginator",paginator) ## 读取当页数据对象 currentGradePage = paginator.page(page_index) gradeList = currentGradePage.object_list ## 获取查询页的数据 # for a in currentGradePage.object_list: # print(a) print("paginator.count-总行数",paginator.count) print("paginator.count-总页数",paginator.num_pages) ## 以 1 为基础的页码范围迭代器 print("paginator.count-以1为基础循环",paginator.page_range) ''' 返回页码 列表 number: int | float | str = ..., *, on_each_side: int = ..., on_ends: int = ... ''' # iterators = paginator.get_elided_page_range(1,on_each_side=3,on_ends=2) # for p in iterators: # print(p) # ## 输入页码 返回 page对象 # page = paginator.get_page(1) # print(page) # ## 如果有下一页,返回 True。 # has_next = page.has_next() # print("has_next:",has_next) # ## 如果有上一页返回true # has_previous = page.has_previous() # print("has_previous:",has_previous) # ## 如果有 上一页或者下一页 返回true # has_other_pages = page.has_other_pages() # print("has_other_pages:",has_other_pages) # ## 返回下一页的页码。如果下一页不存在,则引发 InvalidPage # next_page_number = page.next_page_number() # print("next_page_number:",next_page_number) # ## 返回上一页的页码。如果上一页不存在,则引发 InvalidPage # previous_page_number = page.previous_page_number() # print("previous_page_number:",previous_page_number) # ## 返回页面上第一个对象,相对于分页器列表中所有对象的基于 1 的索引。例如,当对一个有 5 个对象的列表进行分页时,每页有 2 个对象,第二页的 start_index() 将返回 3 # start_index = page.start_index() # print("start_index:",start_index) # ## 返回页面上最后一个对象相对于分页器列表中所有对象的基于 1 的索引。例如,当对一个有 5 个对象的列表进行分页时,每页有 2 个对象,第二页的 end_index() 将返回 4 # end_index = page.end_index() # print("end_index:",end_index) # print(pageIndex) ## 保存变量 context = {"gradeList":gradeList,"currentGradePage":currentGradePage,"pageIndex":pageIndex,"grade_name":grade_name} return render(request=request,template_name="grade/grade_index.html",context=context,content_type='text/html')
4.配置路由地址 urls.py
"""school_web_grade URL ConfigurationThe urlpatterns
list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/4.0/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 adminfrom django.urls import pathfrom django.urls import includefrom . import views## 模块名称 url命名空间app_name = "school_web_grade"'''path(route: str, route 是一个匹配 URL 的准则(类似正则表达式)view: (...) -> HttpResponseBase,当 Django 找到了一个匹配的准则,就会调用这个特定的视图函数,并传入一个 HttpRequest 对象作为第一个参数,被"捕获"的参数以关键字参数的形式传入kwargs: Dict[str, Any] = ...,任意个关键字参数可以作为一个字典传递给目标视图函数name: str = ...为你的 URL 取名能使你在 Django 的任意地方唯一地引用它,尤其是在模板中。这个有用的特性允许你只改一个文件就能全局地修改某个 URL 模式'''urlpatterns = [ ## 默认主页 path(route="",view=views.IndexView.as_view(),name="index"), ## 年级模块 path(route="gradeIndex//",view=views.gradeIndex,name="gradeIndex"),]
5.注册 school\school_web_grade\admin.py
from django.contrib import admin# Register your models here.## 向管理网站注册当前创建的模型from .models import SchoolGrade## 年级类admin.site.register(SchoolGrade)
6.运行项目
总结
初次运行 数据是不存在的 因为没有对数据库进行添加数据操作 ,下一节专门介绍下 新增
Original: https://blog.51cto.com/u_15446828/5507893
Author: 口袋里的小龙
Title: Python-Django 项目模块-年级模块开发(七)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/513265/
转载文章受原作者版权保护。转载请注明原作者出处!