背景:创建一个简单的学生管理系统,熟悉增删改查操作
一:创建一个Django项目
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'); } } ) }) }