背景:创建一个简单的学生管理系统,熟悉增删改查操作
一:创建一个Django项目(http://www.cnblogs.com/wupeiqi/articles/6216618.html)
1:创建实体类
from django.db import models # Create your models here. class Classes(models.Model): # 班级表 title=models.CharField(max_length=32) # 班级-教师:多对多 m=models.ManyToManyField("Teachers") class Teachers(models.Model): # 教师表 name = models.CharField(max_length=32) class Students(models.Model): # 学生表 name=models.CharField(max_length=32) age=models.IntegerField() gender=models.NullBooleanField() # 学生-班级 多对一 cs=models.ForeignKey(Classes)
2:同步到数据库
python manage.py makemigrations
python manage.py migrate
3:考虑到页面逻辑比较多,所以将原来的View.py文件删掉,新增一个View文件夹,把每个页面的业务逻辑创建对应文件(classes.py+students.py+teachers.py)
二:班级表的增删改查(单表操作)
1:展示班级信息列表
a:配置路由
"""StudentManageSystem URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.1/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 App01.Views import classes from django.conf.urls import url urlpatterns = [ url('admin/', admin.site.urls), url(r'^get_classes.html$',classes.get_classes), url(r'^add_classes.html$',classes.add_classes), url(r'^del_classes.html$', classes.del_classes), url(r'^edit_classes.html$', classes.edit_classes) ]
b:view中控制逻辑
from django.shortcuts import render from django.shortcuts import HttpResponse from django.shortcuts import redirect from App01 import models def get_classes(request): cls_list=models.Classes.objects.all() return render(request,"get_classes.html",{'cls_list':cls_list}) def add_classes(request): if request.method=='GET': #如果是通过get请求进来表示只是展示页面 return render(request, "add_classes.html") elif request.method=='POST': title=request.POST.get("title") models.Classes.objects.create(title=title) return redirect("get_classes.html") def del_classes(request): if request.method=='GET': nid = request.GET.get("nid") models.Classes.objects.filter(id=nid).delete() return redirect("get_classes.html") def edit_classes(request): if request.method=='GET': #如果是通过get请求进来表示只是展示页面,注意需要将title值显示到文本框中 nid = request.GET.get("nid") classesEntity=models.Classes.objects.filter(id=nid).first() return render(request, "edit_classes.html",{'classesEntity':classesEntity}) elif request.method=='POST': nid = request.GET.get("nid") title=request.POST.get("title") models.Classes.objects.filter(id=nid).update(title=title) return redirect("get_classes.html")
c:html页面模板设置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <a href="add_classes.html">添加</a> </div> <div> <table border="1"> <thead> <tr> <th>ID</th> <th>名称</th> <th>操作</th> </tr> </thead> <tbody> {% for row in cls_list %} <tr> <td>{{ row.id }}</td> <td>{{ row.title }}</td> <td> <a href="/del_classes.html?nid={{row.id}}">删除</a> | <a href="/edit_classes.html?nid={{row.id}}">编辑</a> </td> </tr> {% endfor %} </tbody> </table> </div> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post" action="add_classes.html"> {% csrf_token %} <input type="text" name="title"> <input type="submit" value="提交"> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post" action="add_classes.html"> {% csrf_token %} <input type="text" name="title"> <input type="submit" value="提交"> </form> </body> </html>
2:运行效果
三:学生表的增删改查(外键操作)
1:展示学生信息列表
a:配置路由
"""StudentManageSystem URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.1/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 App01.Views import classes,students from django.conf.urls import url urlpatterns = [ url('admin/', admin.site.urls), # 班级管理 路由 url(r'^get_classes.html$',classes.get_classes), url(r'^add_classes.html$',classes.add_classes), url(r'^del_classes.html$', classes.del_classes), url(r'^edit_classes.html$', classes.edit_classes), # 学生管理 路由 url(r'^get_students.html$', students.get_students), url(r'^add_students.html$', students.add_students), url(r'^del_students.html$', students.del_students), url(r'^edit_students.html$', students.edit_students) ]
b:view中控制逻辑
from django.shortcuts import render from django.shortcuts import HttpResponse from django.shortcuts import redirect from App01 import models def get_students(request): stu_list=models.Students.objects.all() return render(request,"get_students.html",{'stu_list':stu_list}) def add_students(request): if request.method=='GET': #如果是通过get请求进来表示只是展示页面 cs_list = models.Classes.objects.all() return render(request, "add_students.html",{'cs_list':cs_list}) elif request.method=='POST': name = request.POST.get('name') age = request.POST.get('age') gender = request.POST.get('gender') cs = request.POST.get('cs') models.Students.objects.create( name=name, age=age, gender=gender, cs_id=cs ) return redirect("get_students.html") def del_students(request): if request.method=='GET': nid = request.GET.get("nid") models.Students.objects.filter(id=nid).delete() return redirect("get_students.html") def edit_students(request): if request.method=='GET': #如果是通过get请求进来表示只是展示页面,注意需要将title值显示到文本框中 nid = request.GET.get("nid") obj=models.Students.objects.filter(id=nid).first() cs_list = models.Classes.objects.all() return render(request, "edit_students.html",{'obj':obj,'cs_list':cs_list}) elif request.method=='POST': nid = request.GET.get("nid") name = request.POST.get('name') age = request.POST.get('age') gender = request.POST.get('gender') cs = request.POST.get('cs') models.Students.objects.filter(id=nid).update(name=name,age=age,gender=gender,cs_id=cs) return redirect("get_students.html")
c:html页面模板设置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <a href="add_students.html">添加</a> </div> <div> <table border="1"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>年龄</th> <th>性别</th> <th>班级</th> <th>操作</th> </tr> </thead> <tbody> {% for row in stu_list %} <tr> <td>{{ row.id }}</td> <td>{{ row.name }}</td> <td>{{ row.age }}</td> {% if row.gender %} <td>男</td> {% else %} <td>女</td> {% endif %} <td>{{ row.cs.title }}</td> <td> <a href="/del_students.html?nid={{row.id}}">删除</a> | <a href="/edit_students.html?nid={{row.id}}">编辑</a> </td> </tr> {% endfor %} </tbody> </table> </div> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post" action="add_students.html"> {% csrf_token %} <p><input type="text" name="name" placeholder="请输入姓名"></p> <p><input type="text" name="age" placeholder="请输入年龄"></p> <p> <input type="radio" name="gender" value="1">男 <input type="radio" name="gender" value="0">女 </p> <p> <select name="cs"> {% for row in cs_list %} <option value="{{ row.id }}">{{ row.title }}</option> {% endfor %} </select> </p> <p><input type="submit" value="提交"></p> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="edit_students.html?nid={{ obj.id }}" method="POST"> {% csrf_token %} {# <p style="display: none"> <input type="text" name="id" value="{{ obj.id }}" /></p>#} <p> <input type="text" name="name" value="{{ obj.name }}" /></p> <p> <input type="text" name="age" value="{{ obj.age }}" /></p> <p> {% if obj.gender %} 男:<input type="radio" name="gender" checked="checked" value="1" /> 女:<input type="radio" name="gender" value="0" /> {% else %} 男:<input type="radio" name="gender" value="1" /> 女:<input type="radio" name="gender" value="0" checked="checked" /> {% endif %} </p> <p> <select name="cs"> {% for row in cs_list %} {% if row.id == obj.cs_id %} <option value="{{ row.id }}" selected="selected" >{{ row.title }}</option> {% else %} <option value="{{ row.id }}">{{ row.title }}</option> {% endif %} {% endfor %} </select> </p> <input type="submit" value="提交" /> </form> </body> </html>
2:运行效果
四、为班级分配教师
a:配置路由
url(r'^set_teachers.html$', classes.set_teachers),
b:view中控制逻辑
def set_teachers(request): if request.method=='GET': #如果是通过get请求进来表示只是展示页面,注意需要将班级已有的教师选中 nid = request.GET.get("nid") # 获取当前班级 classesEntity = models.Classes.objects.filter(id=nid).first() #获取所有的教师 teachersList = models.Teachers.objects.all() # 获取当前班级已分配的教师 selectTeacherList=classesEntity.m.all() return render(request, "set_teachers.html",{'classesEntity':classesEntity,'teachersList':teachersList,'selectTeacherList':selectTeacherList}) elif request.method=='POST': nid = request.GET.get("nid") # 注意,这里是设置getlist() selectTeacherIds=request.POST.getlist("selectTeacherIds") print(111) print(selectTeacherIds) models.Classes.objects.filter(id=nid).first().m.set(selectTeacherIds) return redirect("get_classes.html")
c:html页面模板设置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post" action="set_teachers.html?nid={{ classesEntity.id }}"> {% csrf_token %} <select multiple="multiple" size="10" name="selectTeacherIds"> {% for teacher in teachersList %} {% if teacher in selectTeacherList %} <option value="{{ teacher.id }}" selected="selected">{{ teacher.name }}</option> {% else %} <option value="{{ teacher.id }}">{{ teacher.name }}</option> {% endif %} {% endfor %} </select> <input type="submit" value="提交"> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <a href="add_classes.html">添加</a> </div> <div> <table border="1"> <thead> <tr> <th>ID</th> <th>名称</th> <th>任课老师</th> <th>操作</th> </tr> </thead> <tbody> {% for row in cls_list %} <tr> <td>{{ row.id }}</td> <td>{{ row.title }}</td> <td> {% for item in row.m.all %} <span>{{ item.name }}</span> {% endfor %} </td> <td> <a href="/del_classes.html?nid={{row.id}}">删除</a> | <a href="/edit_classes.html?nid={{row.id}}">编辑</a> | <a href="/set_teachers.html?nid={{row.id}}">分配教师</a> </td> </tr> {% endfor %} </tbody> </table> </div> </body> </html>
学生管理系统2.0版本
接下啦我们使用一些常用的组件,对系统的页面和功能进行优化
五:页面优化
配置static文件夹,用于存放一些外部的引用(js、css等其他插件)
1:下载和使用bootstrap插件
2:如果Bootstrap中的icon的内容不符合我们的要求我们还可以使用Font Awesome图标字体库,(我这里就不用了)
3:修改setting中的MIDDLEWARE的csrf
""" Django settings for StudentManageSystem project. Generated by 'django-admin startproject' using Django 2.1.5. For more information on this file, see https://docs.djangoproject.com/en/2.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.1/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '&6e&089_g+(58rk7&jh^)ewqe3_-xujk%0u(ukgi&6_jj28r)@' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'App01.apps.App01Config', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'StudentManageSystem.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'StudentManageSystem.wsgi.application' # Database # https://docs.djangoproject.com/en/2.1/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/2.1/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.1/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS=( os.path.join(BASE_DIR,'static'), )
4:配置url学生管理2.0 路由
"""StudentManageSystem URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.1/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 App01.Views import classes,students from django.conf.urls import url urlpatterns = [ url('admin/', admin.site.urls), # 班级管理 路由 url(r'^get_classes.html$',classes.get_classes), url(r'^add_classes.html$',classes.add_classes), url(r'^del_classes.html$', classes.del_classes), url(r'^edit_classes.html$', classes.edit_classes), # 为班级分配老师 url(r'^set_teachers.html$', classes.set_teachers), # 学生管理 路由 url(r'^get_students.html$', students.get_students), url(r'^add_students.html$', students.add_students), url(r'^del_students.html$', students.del_students), url(r'^edit_students.html$', students.edit_students), # 学生管理2.0 路由 url(r'^addStudent$', students.addStudent), ]
5:学生页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> {#引入css和Bootstrap#} <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/plugins/fontawesome/css/fontawesome.css"> </head> <body> <div class="container"> <a class="btn btn-primary" id="addBtn">添加</a> <a class="btn btn-danger" id="delBtn">删除</a> <table class="table table-hover table-bordered"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>年龄</th> <th>性别</th> <th>班级</th> <th>操作</th> </tr> </thead> <tbody> {% for row in stu_list %} <tr> <td>{{ row.id }}</td> <td>{{ row.name }}</td> <td>{{ row.age }}</td> {% if row.gender %} <td>男</td> {% else %} <td>女</td> {% endif %} <td>{{ row.cs.title }}</td> <td> <a class="glyphicon glyphicon-remove"></a> <i class="glyphicon glyphicon-pencil"></i> </td> </tr> {% endfor %} </tbody> </table> </div> <!-- Modal --> <div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span> </button> <h4 class="modal-title" id="myModalLabel">学生信息</h4> </div> <div class="modal-body"> <form class="form-horizontal" id="formStudentInfo"> <div class="form-group"> <label for="userName" class="col-sm-2 control-label">姓名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="userName" name="userName" placeholder="请输入姓名"> </div> </div> <div class="form-group"> <label for="age" class="col-sm-2 control-label">年龄</label> <div class="col-sm-10"> <input type="text" class="form-control" id="age" name="age" placeholder="年龄"> </div> </div> <div class="form-group"> <label for="gender" class="col-sm-2 control-label">性别</label> <div class="col-sm-10"> <label class="radio-inline"> <input type="radio" name="gender" value="1"> 男 </label> <label class="radio-inline"> <input type="radio" name="gender" value="0"> 女 </label> </div> </div> <div class="form-group"> <label for="classes" class="col-sm-2 control-label">班级</label> <div class="col-sm-10"> <select class="form-control" id="cls_ids" name="cls_ids"> {% for item in cs_list %} <option value="{{ item.id }}">{{ item.title }}</option> {% endfor %} </select> </div> </div> </form> </div> <div class="modal-footer"> <span id="errorMsg" style="color: red"></span> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="btnSave">保存</button> </div> </div> </div> </div> {#引入jQuery和Bootstrap#} <script src="/static/js/jquery-3.3.1.min.js"></script> <script src="/static/plugins/bootstrap/js/bootstrap.js"></script> <script> $(function () { bindEvent(); bindSave(); }) {#给添加按钮绑定,弹出模态窗口的事件#} function bindEvent() { $("#addBtn").click(function () { $("#addModal").modal('show'); }) } {#给保存按钮绑定调用后台事件#} function bindSave() { $("#btnSave").click(function () { var datas = {} {#遍历页面上所有的控件#} $("#formStudentInfo").find("input,select").each(function () { debugger; var v = $(this).val(); var n = $(this).attr('name'); if (n == "gender") { if ($(this).prop("checked")) { datas[n] = v; } } else { datas[n] = v; } }); $.ajax({ url: "addStudent", type: 'POST', data: datas, success: function (arg) { {# 将返回的信息,转化成数据#} var mess=JSON.parse(arg); if(mess.status){ {#添加成功,刷新页面#} window.location.reload() }else{ $("#errorMsg").text(mess.message) } } }) }) } </script> </body> </html>
6:后台处理页面
from django.shortcuts import render from django.shortcuts import HttpResponse from django.shortcuts import redirect from App01 import models import json def get_students(request): stu_list = models.Students.objects.all() cs_list = models.Classes.objects.all() return render(request, "get_students.html", {'stu_list': stu_list, 'cs_list': cs_list}) def add_students(request): if request.method == 'GET': # 如果是通过get请求进来表示只是展示页面 cs_list = models.Classes.objects.all() return render(request, "add_students.html", {'cs_list': cs_list}) elif request.method == 'POST': name = request.POST.get('name') age = request.POST.get('age') gender = request.POST.get('gender') cs = request.POST.get('cs') models.Students.objects.create( name=name, age=age, gender=gender, cs_id=cs ) return redirect("get_students.html") def del_students(request): if request.method == 'GET': nid = request.GET.get("nid") models.Students.objects.filter(id=nid).delete() return redirect("get_students.html") def edit_students(request): if request.method == 'GET': # 如果是通过get请求进来表示只是展示页面,注意需要将title值显示到文本框中 nid = request.GET.get("nid") obj = models.Students.objects.filter(id=nid).first() cs_list = models.Classes.objects.all() return render(request, "edit_students.html", {'obj': obj, 'cs_list': cs_list}) elif request.method == 'POST': nid = request.GET.get("nid") name = request.POST.get('name') age = request.POST.get('age') gender = request.POST.get('gender') cs = request.POST.get('cs') models.Students.objects.filter(id=nid).update(name=name, age=age, gender=gender, cs_id=cs) return redirect("get_students.html") def addStudent(request): response = {"status":True,"message":None} name = request.POST.get('userName') age = request.POST.get('age') gender = request.POST.get('gender') cs = request.POST.get('cls_ids') try: print(name,age,gender,cs) models.Students.objects.create( name=name, age=age, gender=gender, cs_id=cs ) except: response["status"]=False response["message"]="输入的格式不正确" # 把返回的数据信息先转化成字符串 result = json.dumps(response, ensure_ascii=False) return HttpResponse(result)
7:显示效果
8:修改HTML页面中的js,使得数据添加成功后,不刷新页面
主要实现原理是:ajax回调成功后,拼接一个tr,添加到原来的table中
9:删除功能以及删除bug修改
# 学生管理2.0 路由 url(r'^addStudent$', students.addStudent), url(r'^delStudent$', students.delStudent),
def addStudent(request): response = {"status":True,"message":None,"obj":None} name = request.POST.get('userName') age = request.POST.get('age') gender = request.POST.get('gender') cs = request.POST.get('cls_ids') try: print(name,age,gender,cs) obj=models.Students.objects.create( name=name, age=age, gender=gender, cs_id=cs ) response["obj"] = obj.id print(response) except: response["status"]=False response["message"]="输入的格式不正确" # 把返回的数据信息先转化成字符串 result = json.dumps(response, ensure_ascii=False) return HttpResponse(result) def delStudent(request): response = {"status": True, "message": None, "obj": None} try: nid = request.GET.get("rowID") models.Students.objects.filter(id=nid).delete() except: response["status"] = False response["message"] = "删除失败" # 把返回的数据信息先转化成字符串 result = json.dumps(response, ensure_ascii=False) return HttpResponse(result)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> {#引入css和Bootstrap#} <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/plugins/fontawesome/css/fontawesome.css"> </head> <body> <div class="container"> <a class="btn btn-primary" id="addBtn">添加</a> <a class="btn btn-danger" id="delBtn">删除</a> <table id="tbStudentsList" class="table table-hover table-bordered"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>年龄</th> <th>性别</th> <th>班级</th> <th>操作</th> </tr> </thead> <tbody> {% for row in stu_list %} <tr nid="{{ row.id }}"> <td>{{ row.id }}</td> <td>{{ row.name }}</td> <td>{{ row.age }}</td> {% if row.gender %} <td>男</td> {% else %} <td>女</td> {% endif %} <td>{{ row.cs.title }}</td> <td> <a class="glyphicon glyphicon-remove del-row"></a> <i class="glyphicon glyphicon-pencil"></i> </td> </tr> {% endfor %} </tbody> </table> </div> <!-- 添加模态窗口 --> <div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span> </button> <h4 class="modal-title" id="myModalLabel">学生信息</h4> </div> <div class="modal-body"> <form class="form-horizontal" id="formStudentInfo"> <div class="form-group"> <label for="userName" class="col-sm-2 control-label">姓名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="userName" name="userName" placeholder="请输入姓名"> </div> </div> <div class="form-group"> <label for="age" class="col-sm-2 control-label">年龄</label> <div class="col-sm-10"> <input type="text" class="form-control" id="age" name="age" placeholder="年龄"> </div> </div> <div class="form-group"> <label for="gender" class="col-sm-2 control-label">性别</label> <div class="col-sm-10"> <label class="radio-inline"> <input type="radio" name="gender" value="1"> 男 </label> <label class="radio-inline"> <input type="radio" name="gender" value="0"> 女 </label> </div> </div> <div class="form-group"> <label for="classes" class="col-sm-2 control-label">班级</label> <div class="col-sm-10"> <select class="form-control" id="cls_ids" name="cls_ids"> {% for item in cs_list %} <option value="{{ item.id }}">{{ item.title }}</option> {% endfor %} </select> </div> </div> </form> </div> <div class="modal-footer"> <span id="errorMsg" style="color: red"></span> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="btnSave">保存</button> </div> </div> </div> </div> <!-- 删除模态窗口 --> <div class="modal fade" id="delModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="alert alert-danger" role="alert"> <h3>删除学生信息?</h3> <div>...<input style="display: none;" type="text" id="delNid"/></div> <div> <button id="cancelConfirm" type="button" class="btn btn-default">取消</button> <button id="delConfirm" type="button" class="btn btn-danger">确定</button> </div> </div> </div> </div> {#引入jQuery和Bootstrap#} <script src="/static/js/jquery-3.3.1.min.js"></script> <script src="/static/plugins/bootstrap/js/bootstrap.js"></script> <script> $(function () { bindEvent(); bindSave(); bindDel(); }) {#给添加按钮绑定,弹出模态窗口的事件#} function bindEvent() { $("#addBtn").click(function () { $("#addModal").modal('show'); }) } {#给保存按钮绑定调用后台事件#} function bindSave() { $("#btnSave").click(function () { var datas = {} {#遍历页面上所有的控件#} $("#formStudentInfo").find("input,select").each(function () { var v = $(this).val(); var n = $(this).attr('name'); if (n == "gender") { if ($(this).prop("checked")) { datas[n] = v; } } else { datas[n] = v; } {#添加一个班级名称,方便后面不刷新页面直接显示的时候使用#} if (n == "cls_ids") { datas["classesName"] = $("#cls_ids option:selected").text(); } }); $.ajax({ url: "addStudent", type: 'POST', data: datas, success: function (arg) { {# 将返回的信息,转化成数据#} var mess = JSON.parse(arg); if (mess.status) { {#添加成功,刷新页面#} {#window.location.reload()#} {#添加成功,不刷新页面#} createNewRecord(datas, mess.obj) $("#addModal").modal('hide'); } else { $("#errorMsg").text(mess.message) } } }) }) } function createNewRecord(data, obj) { var tr = document.createElement('tr'); {#id#} var tid = '<td>' + obj + '</td>'; $(tr).append(tid); {#姓名#} var tName = '<td>' + data.userName + '</td>'; $(tr).append(tName); {#年龄#} var tage = '<td>' + data.age + '</td>'; $(tr).append(tage); {#性别#} var tdGender = document.createElement('td'); if (data.gender == "0") { tdGender.innerHTML = '女'; } else { tdGender.innerHTML = '男'; } $(tr).append(tdGender); {#班级#} var tdclassName = '<td>' + data.classesName + '</td>'; $(tr).append(tdclassName); var tdHandle = '<td><a class="glyphicon glyphicon-remove"></a><i class="glyphicon glyphicon-pencil"></i></td>'; $(tr).append(tdHandle); $('#tbStudentsList').append(tr); } {#给删除按钮绑定,弹出模态窗口的事件#} function bindDel() { {#点击每一行的删除链接#} $(".del-row").click(function () { {#把删除的nid赋值给弹出窗口中的id#} var rowId=$(this).parent().parent().attr('nid'); $("#delNid").val(rowId) $("#delModal").modal('show'); }) {#弹出删除对话框后,取消按钮#} $("#cancelConfirm").click(function () { $("#delModal").modal('hide'); }) {#弹出删除确认对话框后,确定按钮#} $("#delConfirm").click(function () { var rowID =$("#delNid").val(); $.ajax({ url: "delStudent", type: 'get', data: {"rowID":rowID}, success: function (arg) { {# 将返回的信息,转化成数据#} var mess = JSON.parse(arg); if (mess.status) { {#删除成功,不刷新页面#} $('tr[nid="'+rowID+'"]').remove(); } $("#delModal").modal('hide'); } } ) }) } </script> </body> </html>
存在的bug:新增之后,再次点击删除,发现没有触发事件。
原因分析:页面没有重新加载,绑定事件没有触发。可以通过事件委托来实现
function createNewRecord(data, obj) { var tr = document.createElement('tr'); $(tr).attr("nid",obj) {#id#} var tid = '<td>' + obj + '</td>'; $(tr).append(tid); {#姓名#} var tName = '<td>' + data.userName + '</td>'; $(tr).append(tName); {#年龄#} var tage = '<td>' + data.age + '</td>'; $(tr).append(tage); {#性别#} var tdGender = document.createElement('td'); if (data.gender == "0") { tdGender.innerHTML = '女'; } else { tdGender.innerHTML = '男'; } $(tr).append(tdGender); {#班级#} var tdclassName = '<td>' + data.classesName + '</td>'; $(tr).append(tdclassName); var tdHandle = '<td><a class="glyphicon glyphicon-remove del-row"></a><i class="glyphicon glyphicon-pencil"></i></td>'; $(tr).append(tdHandle); $('#tbStudentsList').append(tr); }
function bindDel() { {#点击每一行的删除链接#} {#事件委托,解决新增的数据没有绑定删除事件的bug#} $("#tbStudentsList").on("click",".del-row",function () { {#把删除的nid赋值给弹出窗口中的id#} var rowId=$(this).parent().parent().attr('nid'); $("#delNid").val(rowId) $("#delModal").modal('show'); }) {#弹出删除对话框后,取消按钮#} $("#cancelConfirm").click(function () { $("#delModal").modal('hide'); }) {#弹出删除确认对话框后,确定按钮#} $("#delConfirm").click(function () { var rowID =$("#delNid").val(); $.ajax({ url: "delStudent", type: 'get', data: {"rowID":rowID}, success: function (arg) { {# 将返回的信息,转化成数据#} var mess = JSON.parse(arg); if (mess.status) { {#删除成功,不刷新页面#} $('tr[nid="'+rowID+'"]').remove(); } $("#delModal").modal('hide'); } } ) }) }
10:编辑功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> {#引入css和Bootstrap#} <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/plugins/fontawesome/css/fontawesome.css"> </head> <body> <div class="container"> <a class="btn btn-primary" id="addBtn">添加</a> <a class="btn btn-danger" id="delBtn">删除</a> <table id="tbStudentsList" class="table table-hover table-bordered"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>年龄</th> <th>性别</th> <th>班级</th> <th>操作</th> </tr> </thead> <tbody> {% for row in stu_list %} <tr nid="{{ row.id }}"> <td na="entityId">{{ row.id }}</td> <td na="entityName">{{ row.name }}</td> <td na="entityAge">{{ row.age }}</td> {% if row.gender %} <td na="entityGender">男</td> {% else %} <td na="entityGender">女</td> {% endif %} <td na="entityClassName">{{ row.cs.title }}</td> <td> <a class="glyphicon glyphicon-remove del-row"></a> <a class="glyphicon glyphicon-pencil edit-row"></a> </td> </tr> {% endfor %} </tbody> </table> </div> <!-- 添加模态窗口 --> <div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span> </button> <h4 class="modal-title" id="myModalLabel">学生信息</h4> </div> <div class="modal-body"> <form class="form-horizontal" id="formStudentInfo"> <div class="form-group"> <label for="userName" class="col-sm-2 control-label">姓名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="userName" name="userName" placeholder="请输入姓名"> </div> </div> <div class="form-group"> <label for="age" class="col-sm-2 control-label">年龄</label> <div class="col-sm-10"> <input type="text" class="form-control" id="age" name="age" placeholder="年龄"> </div> </div> <div class="form-group"> <label for="gender" class="col-sm-2 control-label">性别</label> <div class="col-sm-10"> <label class="radio-inline"> <input type="radio" name="gender" value="1"> 男 </label> <label class="radio-inline"> <input type="radio" name="gender" value="0"> 女 </label> </div> </div> <div class="form-group"> <label for="classes" class="col-sm-2 control-label">班级</label> <div class="col-sm-10"> <select class="form-control" id="cls_ids" name="cls_ids"> {% for item in cs_list %} <option value="{{ item.id }}">{{ item.title }}</option> {% endfor %} </select> </div> </div> </form> </div> <div class="modal-footer"> <span id="errorMsg" style="color: red"></span> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="btnSave">保存</button> </div> </div> </div> </div> <!-- 删除模态窗口 --> <div class="modal fade" id="delModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="alert alert-danger" role="alert"> <h3>删除学生信息?</h3> <div>...<input style="display: none;" type="text" id="delNid"/></div> <div> <button id="cancelConfirm" type="button" class="btn btn-default">取消</button> <button id="delConfirm" type="button" class="btn btn-danger">确定</button> </div> </div> </div> </div> <!-- 编辑模态窗口 --> <div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span> </button> <h4 class="modal-title" id="myModalLabel">学生信息</h4> </div> <div class="modal-body"> <form class="form-horizontal" id="formStudentInfo"> <div class="form-group" style="display: none"> <label for="id" class="col-sm-2 control-label">用户id</label> <div class="col-sm-10"> <input type="text" class="form-control" id="id" name="nid" na="entityId"> </div> </div> <div class="form-group"> <label for="userName" class="col-sm-2 control-label">姓名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="userName" name="userName" placeholder="请输入姓名" na="entityName"> </div> </div> <div class="form-group"> <label for="age" class="col-sm-2 control-label">年龄</label> <div class="col-sm-10"> <input type="text" class="form-control" id="age" name="age" placeholder="年龄" na="entityAge"> </div> </div> <div class="form-group"> <label for="gender" class="col-sm-2 control-label">性别</label> <div class="col-sm-10"> <label class="radio-inline"> <input type="radio" name="gender" value="1" na="entityGender"> 男 </label> <label class="radio-inline"> <input type="radio" name="gender" value="0" na="entityGender"> 女 </label> </div> </div> <div class="form-group"> <label for="classes" class="col-sm-2 control-label">班级</label> <div class="col-sm-10"> <select class="form-control" id="cls_ids" name="cls_ids" na="entityClassName"> {% for item in cs_list %} <option value="{{ item.id }}">{{ item.title }}</option> {% endfor %} </select> </div> </div> </form> </div> <div class="modal-footer"> <span id="errorMsg" style="color: red"></span> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="btnSave">保存</button> </div> </div> </div> </div> {#引入jQuery和Bootstrap#} <script src="/static/js/jquery-3.3.1.min.js"></script> <script src="/static/plugins/bootstrap/js/bootstrap.js"></script> <script> $(function () { bindEvent(); bindSave(); bindDel(); bindEdit(); }) {#给添加按钮绑定,弹出模态窗口的事件#} function bindEvent() { $("#addBtn").click(function () { clearEle() $("#addModal").modal('show'); }) } {#给保存按钮绑定调用后台事件#} function bindSave() { $("#addModal #btnSave").click(function () { var datas = {} {#遍历页面上所有的控件#} $("#addModal #formStudentInfo").find("input,select").each(function () { var v = $(this).val(); var n = $(this).attr('name'); if (n == "gender") { if ($(this).prop("checked")) { datas[n] = v; } } else { datas[n] = v; } {#添加一个班级名称,方便后面不刷新页面直接显示的时候使用#} if (n == "cls_ids") { datas["classesName"] = $("#cls_ids option:selected").text(); } }); $.ajax({ url: "addStudent", type: 'POST', data: datas, success: function (arg) { {# 将返回的信息,转化成数据#} var mess = JSON.parse(arg); if (mess.status) { {#添加成功,刷新页面#} {#window.location.reload()#} {#添加成功,不刷新页面#} createNewRecord(datas, mess.obj) $("#addModal").modal('hide'); } else { $("#errorMsg").text(mess.message) } } }) }) } function createNewRecord(data, obj) { var tr = document.createElement('tr'); $(tr).attr("nid", obj) {#id#} var tid = '<td na="entityId">' + obj + '</td>'; $(tr).append(tid); {#姓名#} var tName = '<td na="entityName">' + data.userName + '</td>'; $(tr).append(tName); {#年龄#} var tage = '<td na="entityAge">' + data.age + '</td>'; $(tr).append(tage); {#性别#} var tdGender = document.createElement('td'); $(tdGender).attr("na", "entityGender") if (data.gender == "0") { tdGender.innerHTML = '女'; } else { tdGender.innerHTML = '男'; } $(tr).append(tdGender); {#班级#} var tdclassName = '<td na="entityClassName">' + data.classesName + '</td>'; $(tr).append(tdclassName); var tdHandle = '<td><a class="glyphicon glyphicon-remove del-row"></a><i class="glyphicon glyphicon-pencil edit-row"></i></td>'; $(tr).append(tdHandle); $('#tbStudentsList').append(tr); } {#给删除按钮绑定,弹出模态窗口的事件#} function bindDel() { {#点击每一行的删除链接#} {#事件委托,解决新增的数据没有绑定删除事件的bug#} $("#tbStudentsList").on("click", ".del-row", function () { {#把删除的nid赋值给弹出窗口中的id#} var rowId = $(this).parent().parent().attr('nid'); $("#delNid").val(rowId) $("#delModal").modal('show'); }) {#弹出删除对话框后,取消按钮#} $("#cancelConfirm").click(function () { $("#delModal").modal('hide'); }) {#弹出删除确认对话框后,确定按钮#} $("#delConfirm").click(function () { var rowID = $("#delNid").val(); $.ajax({ url: "delStudent", type: 'get', data: {"rowID": rowID}, success: function (arg) { {# 将返回的信息,转化成数据#} var mess = JSON.parse(arg); if (mess.status) { {#删除成功,不刷新页面#} $('tr[nid="' + rowID + '"]').remove(); } $("#delModal").modal('hide'); } } ) }) } {#给编辑按钮绑定,弹出模态窗口的事件#} function bindEdit() { {# 初始化页面,把要编辑的内容展示到页面上对应的字段#} initEditModal(); {# 初始化页面,把要编辑的内容页面上的按钮进行事件绑定#} bindEditSave(); } function initEditModal() { {# 通过委托,来实现每一个编辑按钮的设置#} $("#tbStudentsList").on('click', '.edit-row', function () { clearEle() $("#editModal").modal("show") $(this).parent().prevAll().each(function () { var tdName = $(this).attr('na') var tdValue = $(this).text() if (tdName == "entityClassName") { $("#editModal #cls_ids option").each(function (i, n) { if ($(n).text() == tdValue) { $(n).attr("selected", true); } }) } else if (tdName == "entityGender") { if (tdValue == '男') { $('#editModal :radio[value="1"]').prop('checked', true); } else { $('#editModal :radio[value="0"]').prop('checked', true); } } else { $("#editModal input[na='" + tdName + "']").val(tdValue) } }) }) } function bindEditSave() { $("#editModal #btnSave").click(function () { var datas = {} {#遍历页面上所有的控件#} $("#editModal #formStudentInfo").find("input,select").each(function () { var v = $(this).val(); var n = $(this).attr('name'); if (n == "gender") { if ($(this).prop("checked")) { datas[n] = v; } } else { datas[n] = v; } {#添加一个班级名称,方便后面不刷新页面直接显示的时候使用#} if (n == "cls_ids") { datas["classesName"] = $("#cls_ids option:selected").text(); } }); $.ajax({ url: "editStudent", type: 'POST', data: datas, {# 将返回的信息,转化成数据#} dataType: 'JSON', success: function (arg) { if (arg.status) { window.location.reload() $("#addModal").modal('hide'); } else { $("#errorMsg").text(arg.message) } } }) }) } function clearEle() { $("#addModal #formStudentInfo").find("input[type!='radio']").each(function () { $(this).val(''); }); $("#editModal #formStudentInfo").find("input[type!='radio']").each(function () { {#$(this).val('');#} }); } </script> </body> </html>
from django.shortcuts import render from django.shortcuts import HttpResponse from django.shortcuts import redirect from App01 import models import json def get_students(request): stu_list = models.Students.objects.all() cs_list = models.Classes.objects.all() return render(request, "get_students.html", {'stu_list': stu_list, 'cs_list': cs_list}) def add_students(request): if request.method == 'GET': # 如果是通过get请求进来表示只是展示页面 cs_list = models.Classes.objects.all() return render(request, "add_students.html", {'cs_list': cs_list}) elif request.method == 'POST': name = request.POST.get('name') age = request.POST.get('age') gender = request.POST.get('gender') cs = request.POST.get('cs') models.Students.objects.create( name=name, age=age, gender=gender, cs_id=cs ) return redirect("get_students.html") def del_students(request): if request.method == 'GET': nid = request.GET.get("nid") models.Students.objects.filter(id=nid).delete() return redirect("get_students.html") def edit_students(request): if request.method == 'GET': # 如果是通过get请求进来表示只是展示页面,注意需要将title值显示到文本框中 nid = request.GET.get("nid") obj = models.Students.objects.filter(id=nid).first() cs_list = models.Classes.objects.all() return render(request, "edit_students.html", {'obj': obj, 'cs_list': cs_list}) elif request.method == 'POST': nid = request.GET.get("nid") name = request.POST.get('name') age = request.POST.get('age') gender = request.POST.get('gender') cs = request.POST.get('cs') models.Students.objects.filter(id=nid).update(name=name, age=age, gender=gender, cs_id=cs) return redirect("get_students.html") def addStudent(request): response = {"status":True,"message":None,"obj":None} name = request.POST.get('userName') age = request.POST.get('age') gender = request.POST.get('gender') if gender : pass else: gender = 1 cs = request.POST.get('cls_ids') try: print(name,age,gender,cs) obj=models.Students.objects.create( name=name, age=age, gender=gender, cs_id=cs ) response["obj"] = obj.id print(response) except: response["status"]=False response["message"]="输入的格式不正确" # 把返回的数据信息先转化成字符串 result = json.dumps(response, ensure_ascii=False) return HttpResponse(result) def delStudent(request): response = {"status": True, "message": None, "obj": None} try: nid = request.GET.get("rowID") models.Students.objects.filter(id=nid).delete() except: response["status"] = False response["message"] = "删除失败" # 把返回的数据信息先转化成字符串 result = json.dumps(response, ensure_ascii=False) return HttpResponse(result) def editStudent(request): response = {"status": True, "message": None, "obj": None} nid = request.POST.get('nid') name = request.POST.get('userName') age = request.POST.get('age') gender = request.POST.get('gender') if gender: pass else: gender = 1 cs = request.POST.get('cls_ids') try: print(name, age, gender, cs) models.Students.objects.filter(id=nid).update(name=name, age=age, gender=gender, cs_id=cs) except: response["status"] = False response["message"] = "输入的格式不正确" # 把返回的数据信息先转化成字符串 result = json.dumps(response, ensure_ascii=False) return HttpResponse(result)
11:分页功能
"""StudentManageSystem URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.1/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 App01.Views import classes,students,pagingTest from django.conf.urls import url urlpatterns = [ url('admin/', admin.site.urls), # 班级管理 路由 url(r'^get_classes.html$',classes.get_classes), url(r'^add_classes.html$',classes.add_classes), url(r'^del_classes.html$', classes.del_classes), url(r'^edit_classes.html$', classes.edit_classes), # 为班级分配老师 url(r'^set_teachers.html$', classes.set_teachers), # 学生管理 路由 url(r'^get_students.html$', students.get_students), url(r'^add_students.html$', students.add_students), url(r'^del_students.html$', students.del_students), url(r'^edit_students.html$', students.edit_students), # 学生管理2.0 路由 url(r'^addStudent$', students.addStudent), url(r'^delStudent$', students.delStudent), url(r'^editStudent$', students.editStudent), # 分页测试 路由 url(r'^pagingTest1$', pagingTest.test1), url(r'^pagingTest2$', pagingTest.test2), ]
from django.shortcuts import render from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger # 模拟数据 USER_LIST=[] for i in range(1,666): temp={'name':'root'+str(i),"age":i} USER_LIST.append(temp) def test1(request): # 定义每页的显示数目 per_page_num=10 # 获取当前页码 current_page=request.GET.get('p') current_page=int(current_page) # 计算起始位置 start = (current_page-1)*per_page_num end=current_page*per_page_num data=USER_LIST[start:end] # 定义上一页、下一页 prev_pager=current_page-1 next_pager=current_page+1 if current_page<=1: prev_page=1 return render(request,'pagingTest1.html',{'user_list':data,'prev_pager':prev_pager,'next_pager':next_pager}) # django内部的分页 def test2(request): # 全部数据 USER_LIST # 每页显示条目数量 per_page # 数据总个数 count # 总页数的索引范围,如(1,10) page_range # 是否具有下一页、上一页 page对象 current_page=request.GET.get("p") paginator = Paginator(USER_LIST, 10) try: #Page对象 posts=paginator.page(current_page) # has_next 是否有下一页 # next_page_number 下一页页码 # has_prev 是否有上一页 # prev_page_number 上一页页码 # object_list 分页之后的数据列表 # number 当前页 # paginator对象 except PageNotAnInteger: posts=paginator.page(1) except EmptyPage: posts = paginator.page(paginator.num_page) return render(request,'pagingTest1.html',{'posts':posts})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for row in posts %} <li>{{ row.name }}--{{ row.age }}</li> {% endfor %} </ul> {% if posts.has_previous %} <a href="pagingTest2?p={{ posts.previous_page_number }}">上一页</a> {% else %} <a href="#">上一页</a> {% endif %} {% if posts.has_next %} <a href="pagingTest2?p={{ posts.next_page_number }}">下一页</a> {% else %} <a href="#">下一页</a> {% endif %} {{ posts.number }}-{{ posts.paginator.num_pages }} </body> </html>
我们还可以把分页的导航条单独放置到一个模板文件中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for row in posts %} <li>{{ row.name }}--{{ row.age }}</li> {% endfor %} </ul> {% include 'include/page_par.html' %} </body> </html>
{% if posts.has_previous %} <a href="pagingTest2?p={{ posts.previous_page_number }}">上一页</a> {% else %} <a href="#">上一页</a> {% endif %} {% if posts.has_next %} <a href="pagingTest2?p={{ posts.next_page_number }}">下一页</a> {% else %} <a href="#">下一页</a> {% endif %} {{ posts.number }}/{{ posts.paginator.num_pages }}
我们还可以添加页码条
from django.shortcuts import render from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger # 模拟数据 USER_LIST=[] for i in range(1,666): temp={'name':'root'+str(i),"age":i} USER_LIST.append(temp) def test1(request): # 定义每页的显示数目 per_page_num=10 # 获取当前页码 current_page=request.GET.get('p') current_page=int(current_page) # 计算起始位置 start = (current_page-1)*per_page_num end=current_page*per_page_num data=USER_LIST[start:end] # 定义上一页、下一页 prev_pager=current_page-1 next_pager=current_page+1 if current_page<=1: prev_page=1 return render(request,'pagingTest1.html',{'user_list':data,'prev_pager':prev_pager,'next_pager':next_pager}) # django内部的分页 def test3(request): # 全部数据 USER_LIST # 每页显示条目数量 per_page # 数据总个数 count # 总页数的索引范围,如(1,10) page_range # 是否具有下一页、上一页 page对象 current_page=request.GET.get("p") paginator = Paginator(USER_LIST, 10) try: #Page对象 posts=paginator.page(current_page) # has_next 是否有下一页 # next_page_number 下一页页码 # has_prev 是否有上一页 # prev_page_number 上一页页码 # object_list 分页之后的数据列表 # number 当前页 # paginator对象 except PageNotAnInteger: posts=paginator.page(1) except EmptyPage: posts = paginator.page(paginator.num_page) return render(request,'pagingTest1.html',{'posts':posts}) # 有导航条的分页 class MyPaginator(Paginator): def __init__(self,current_page,total_page_par,*args,**kwargs): # 当前页 self.current_page=int(current_page) # 设置总的页码值 self.total_page_par=int(total_page_par) super(MyPaginator,self).__init__(*args, **kwargs) def page_par_range(self): # 总页数( self.num_pages) 总页码数(self.total_page_par) 当前页(self.current_page) # 如果总页数<总页码数 if self.num_pages<self.total_page_par: return range(1,self.num_pages+1) # 如果当前页数<总页码数/2 part = self.total_page_par//2 if self.current_page < part: return range(1,self.total_page_par+1) # 如果当前页+part >总页码数 if self.current_page+part>self.num_pages: return range(self.num_pages-self.total_page_par+1,self.num_pages) return range(self.current_page-part,self.current_page+part) def test2(request): # 通过get获取当前页码 cur_page = request.GET.get("p") print(cur_page) try: paginator = MyPaginator(cur_page, 11, USER_LIST, 10) post=paginator.page(cur_page) except PageNotAnInteger: post=paginator.page(1) except EmptyPage: post=paginator.page(paginator.num_pages) return render(request, 'pagingTest1.html', {'posts': post})
{% if posts.has_previous %} <a href="pagingTest2?p={{ posts.previous_page_number }}">上一页</a> {% else %} <a href="#">上一页</a> {% endif %} {% for row_num in posts.paginator.page_par_range %} {% if row_num == posts.number %} <a style="font-size: 30px;" href="/pagingTest2?p={{ row_num }}">{{ row_num }}</a> {% else %} <a href="pagingTest2?p={{ row_num }}">{{ row_num }}</a> {% endif %} {% endfor %} {% if posts.has_next %} <a href="pagingTest2?p={{ posts.next_page_number }}">下一页</a> {% else %} <a href="#">下一页</a> {% endif %} {{ posts.number }}/{{ posts.paginator.num_pages }}
11:分页组件化
我们可以自已定义一个分页组件
配置url:url(r'^myPageTest$', pagingTest.myPageTest),
# 2.1 所需要的参数 # 序号 字段名 备注 # a data_count 列表的总个数 # b current_page_num当前页码 # C page_rows 每页显示多少行数据(每页显示10条) # D page_num_size 页码条显示个数(建议为奇数,最多页面7个) # 2.2 方法具有的内容 # 序号 字段名 备注 # 1 start 当前页列表显示的初始值 # 2 end 当前页列表显示的结束值 # 3 page_count 总页数 # 4 page_par_range 页码条显示范围 class AaronPager(object): def __init__(self, data_count, current_page_num, page_rows=10, page_num_size=7): # 数据总个数 self.data_count = data_count # 当前页 try: v = int(current_page_num) if v <= 0: v = 1 self.current_page_num = v except Exception as e: self.current_page_num = 1 # 每页显示的行数 self.page_rows = page_rows # 最多显示页面 self.page_num_size = page_num_size def start(self): return (self.current_page_num - 1) * self.page_rows def end(self): return self.current_page_num * self.page_rows @property def page_count(self): # 总页数 a, b = divmod(self.data_count, self.page_rows) if b == 0: return a return a + 1 def page_par_range(self): # 总页数( self.page_count) 总页码数(self.page_num_size) 当前页(self.current_page_num) # 如果总页数<总页码数 if self.page_count < self.page_num_size: return range(1, self.page_count + 1) # 如果当前页数<总页码数/2 part = self.page_num_size // 2 if self.current_page_num < part: return range(1, self.page_num_size + 1) # 如果当前页+part >总页码数 if self.current_page_num + part > self.page_count: return range(self.page_count - self.page_num_size+1, self.page_count+1) return range(self.current_page_num - part, self.current_page_num + part+1) def page_str(self): page_list = [] first = "<li><a href='/myPageTest?p=1'>首页</a></li>" page_list.append(first) if self.current_page_num == 1: prev = "<li><a href='#'>上一页</a></li>" else: prev = "<li><a href='/myPageTest?p=%s'>上一页</a></li>" % (self.current_page_num - 1) page_list.append(prev) for i in self.page_par_range(): if i==self.current_page_num: temp = "<li class='active'><a href='/myPageTest?p=%s'>%s</a></li>" %(i,i) else: temp = "<li><a href='/myPageTest?p=%s'>%s</a></li>" %(i,i) page_list.append(temp) if self.current_page_num == self.page_count: nex = "<li><a href='#'>下一页</a></li>" else: nex = "<li><a href='/myPageTest?p=%s'>下一页</a></li>" %(self.current_page_num + 1) page_list.append(nex) last = "<li><a href='/myPageTest?p=%s'>尾页</a></li>" %(self.page_count) page_list.append(last) return ''.join(page_list)
from django.shortcuts import render from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger # 模拟数据 USER_LIST=[] for i in range(1,666): temp={'name':'root'+str(i),"age":i} USER_LIST.append(temp) def test1(request): # 定义每页的显示数目 per_page_num=10 # 获取当前页码 current_page=request.GET.get('p') current_page=int(current_page) # 计算起始位置 start = (current_page-1)*per_page_num end=current_page*per_page_num data=USER_LIST[start:end] # 定义上一页、下一页 prev_pager=current_page-1 next_pager=current_page+1 if current_page<=1: prev_page=1 return render(request,'pagingTest1.html',{'user_list':data,'prev_pager':prev_pager,'next_pager':next_pager}) # django内部的分页 def test3(request): # 全部数据 USER_LIST # 每页显示条目数量 per_page # 数据总个数 count # 总页数的索引范围,如(1,10) page_range # 是否具有下一页、上一页 page对象 current_page=request.GET.get("p") paginator = Paginator(USER_LIST, 10) try: #Page对象 posts=paginator.page(current_page) # has_next 是否有下一页 # next_page_number 下一页页码 # has_prev 是否有上一页 # prev_page_number 上一页页码 # object_list 分页之后的数据列表 # number 当前页 # paginator对象 except PageNotAnInteger: posts=paginator.page(1) except EmptyPage: posts = paginator.page(paginator.num_page) return render(request,'pagingTest1.html',{'posts':posts}) # 有导航条的分页 class MyPaginator(Paginator): def __init__(self,current_page,total_page_par,*args,**kwargs): # 当前页 self.current_page=int(current_page) # 设置总的页码值 self.total_page_par=int(total_page_par) super(MyPaginator,self).__init__(*args, **kwargs) def page_par_range(self): # 总页数( self.num_pages) 总页码数(self.total_page_par) 当前页(self.current_page) # 如果总页数<总页码数 if self.num_pages<self.total_page_par: return range(1,self.num_pages+1) # 如果当前页数<总页码数/2 part = self.total_page_par//2 if self.current_page < part: return range(1,self.total_page_par+1) # 如果当前页+part >总页码数 if self.current_page+part>self.num_pages: return range(self.num_pages-self.total_page_par+1,self.num_pages) return range(self.current_page-part,self.current_page+part) def test2(request): # 通过get获取当前页码 cur_page = request.GET.get("p") print(cur_page) try: paginator = MyPaginator(cur_page, 11, USER_LIST, 10) post=paginator.page(cur_page) except PageNotAnInteger: post=paginator.page(1) except EmptyPage: post=paginator.page(paginator.num_pages) return render(request, 'pagingTest1.html', {'posts': post}) def myPageTest(request): from App01.AaronPager import AaronPager data_count=666 cur_page=request.GET.get("p") aaron_page = AaronPager(data_count,cur_page,10,7) data_list = USER_LIST[aaron_page.start():aaron_page.end()] return render(request,'aaronTest.html',{'data':data_list,'aaron_page':aaron_page})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.css"> </head> <body> <ul> {% for row in data %} <li>{{ row.name }}--{{ row.age }}</li> {% endfor %} </ul> {% for i in aaron_page.page_par_range %} <a href="/myPageTest?p={{ i }}">{{ i }}</a> {% endfor %} <ul class="pagination pagination-sm"> {{ aaron_page.page_str|safe }} </ul> </body> </html>