跟b站武沛齐老师的视频学习
对学习过程进行一些记录以便复习 同时自我督促 :D冲鸭视频链接: 15天django入门到放弃-哔哩哔哩.
文章目录
回顾
Web框架本质
- 本质:socket
- Http协议:头 + 体
- 字符串
Django
- 安装
- django-admin startproject mysite
- 配置
- 模板路径
- 静态文件
- CSRF注释
- urls.py
- url -> 函数
- 函数
- def index(request):
request.method
request.GET
request.POST
return HttpResponse(…)
return render(request, ‘模板路径’, {})
return redirest(’URL’)
- def index(request):
- 模板渲染
- def index(request):
return render(request, ‘模板路径’, {
‘k1’: ‘v1’,
‘k2’: [1, 2, 3, 4],
‘k3’: {‘x’: …},
}) - index.html
<h1>{{ k1 }}</h1>
<h1>{{ k2.2 }}</h1>
{% for item in k2%}
<h1>{{ item }}</h1>
{% endfor %}
<h1>{{ k3.x }}</h1>
- def index(request):
系统概览
学生管理系统
表:班级 学生 老师
单表操作:增 删 改 查
一对多操作:增 删 改 查
多对多操作:增 删 改 查
数据库表结构设计
表结构:班级\学生\老师
班级表:
id title
1 A班
2 B班
学生表:
id name 班级id(FK)
1 张三 1
老师表:
id name
1 张老师
2 李老师
3 王老师
老师班级关系表:
id 老师id 班级id
1 1 1
2 1 2
3 2 2
项目结构完善
templates
文件夹,用于存放html
文件;- 新增
static
文件夹,用于存放静态文件; - 新增
app01
文件夹,用于存放函数文件。
part1 单表操作
显示班级列表
app01
文件夹下新建 views.py
,在 urls.py
中导入 views
,urlpatterns
中添加 path('classes/', views.classes),
;
编写 classes
函数,连接数据库,读取 id
和 class
,形成 class_list
传给前端:
def classes(request):
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select id, title from class")
class_list = cursor.fetchall()
cursor.close()
conn.close()
return render(request, 'classes.html', {'class_list': class_list})
classes.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>classes</title>
</head>
<body>
<h1>班级列表</h1>
<table>
<thead>
<tr>
<th>id</th>
<th>班级名称</th>
</tr>
</thead>
<tbody>
{% for row in class_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.title }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
实现增加班级功能
在urls.py
里 urlpatterns
中添加 path('add-class/', views.add_class),
;
在 classes.html
中增加“添加”按钮:
<div>
<a href="/add-class/">添加</a>
</div>
前端一个表单,按下“提交按钮”将输入框内数据传回后端,add_class.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add-class</title>
</head>
<body>
<h1>添加班级</h1>
<form method="post" action="/add-class/"> <!--转到add-class路径-->
<p>班级名称:<input type="text" name="title"></p> <!--返回数据的键为title-->
<input type="submit" value="提交">
</form>
</body>
</html>
编写 add_class
函数,初次来到此处时请求类型为 GET
,直接呈现页面;若请求类型为 POST
,则连接数据库,将获取到的 title
内容加入数据库,并回到班级列表展示:
def add_class(request):
if request.method == 'GET':
return render(request, 'add_class.html')
else:
print(request.POST)
title = request.POST.get('title')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("insert into class(title) values(%s)", title)
conn.commit()
cursor.close()
conn.close()
return redirect('/classes/')
注意:redirect 和 render 的区别?
redirect url
render html
实现删除班级功能
在urls.py
里 urlpatterns
中添加 path('del-class/', views.del_class),
;
在 classes.html
中修改表单,增加“操作”栏,每行数据后添加“删除”按钮,链接到 /del-class/
并传 id
回后端:
<table>
<thead>
<tr>
<th>id</th>
<th>班级名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in class_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.title }}</td>
<td><a href="/del-class/?nid={{ row.id }}">删除</a></td>
</tr>
{% endfor %}
</tbody>
</table>
del_class
函数,连接数据库删除 id
对应班级数据:
def del_class(request):
nid = request.GET.get('nid')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("delete from class where id=%s", [nid, ])
conn.commit()
cursor.close()
conn.close()
return redirect('/classes/')
在用户点击“删除”按钮后,实际上进行了两次传递,首先跳转至 /del-class/
执行 del_class
删除了班级数据,然后重定位到 /classes/
执行 classes
重新从数据库获取信息,展示班级列表。
实现编辑班级功能
在urls.py
里 urlpatterns
中添加 path('edit-class/', views.edit_class),
;
在 classes.html
中修改表单,每行数据后添加“编辑”按钮,链接到 /edit-class/
并传 id
回后端:
<td>
<a href="/edit-class/?nid={{ row.id }}">编辑</a>
|
<a href="/del-class/?nid={{ row.id }}">删除</a>
</td>
edit_class.html
与 add_class.html
类似,在其基础上,输入框的默认值应为该数据原本的值,另外需要将所修改数据对应的 id
同时传回后端,因此增加一个不可见的 id
输入框来传递 id
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add-class</title>
</head>
<body>
<h1>编辑班级</h1>
<form method="post" action="/edit-class/">
<input style="display: none" value="{{ result.id }}" name="id">
<p>班级名称:<input type="text" value="{{ result.title }}" name="title"></p> <!--返回数据的键为title-->
<input type="submit" value="提交">
</form>
</body>
</html>
edit_class
函数,仍是分为 GET 和 POST 两种情况:
def edit_class(request):
if request.method == "GET":
nid = request.GET.get('nid')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select id, title from class where id=%s", [nid, ])
result = cursor.fetchone()
cursor.close()
conn.close()
return render(request, 'edit_class.html', {'result': result})
else:
nid = request.POST.get('id')
title = request.POST.get('title')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("update class set title=%s where id=%s", [title, nid, ])
conn.commit()
cursor.close()
conn.close()
return redirect('/classes/')
另一种传递 id
的方法,是在 url
中进行传递,不再需要隐藏输入框,edit_class.html
中表单修改如下:
<form method="post" action="/edit-class/?nid={{ result.id }}">
<p>班级名称:<input type="text" value="{{ result.title }}" name="title"></p> <!--返回数据的键为title-->
<input type="submit" value="提交">
</form>
edit_class
函数修改:
nid = request.GET.get('nid')
title = request.POST.get('title')
相比之下,第二种方法更为简洁。
教师部分(课后作业)
views.py
:
def teachers(request):
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select id, `name` from teacher")
teacher_list = cursor.fetchall()
cursor.close()
conn.close()
return render(request, 'teachers.html', {'teacher_list': teacher_list})
def add_teacher(request):
if request.method == 'GET':
return render(request, 'add_teacher.html')
else:
name = request.POST.get('name')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("insert into teacher(`name`) value(%s)", [name, ])
conn.commit()
cursor.close()
conn.close()
return redirect('/teachers/')
def del_teacher(request):
nid = request.GET.get('nid')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("delete from teacher where id=%s", [nid, ])
conn.commit()
cursor.close()
conn.close()
return redirect('/teachers/')
def edit_teacher(request):
if request.method == 'GET':
nid = request.GET.get('nid')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select id, `name` from teacher where id=%s", [nid, ])
result = cursor.fetchone()
cursor.close()
conn.close()
return render(request, 'edit_teacher.html', {'result': result})
else:
nid = request.GET.get('nid')
name = request.POST.get('name')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("update teacher set `name`=%s where id=%s", [name, nid, ])
conn.commit()
cursor.close()
conn.close()
return redirect('/teachers/')
teachers.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>teachers</title>
</head>
<body>
<h1>教师列表</h1>
<a href="/add-teacher/">添加</a>
<table>
<thead>
<tr>
<th>id</th>
<th>教师名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in teacher_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
<td>
<a href="/edit-teacher/?nid={{ row.id }}">编辑</a>
|
<a href="/del-teacher/?nid={{ row.id }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
add_teacher.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add_teacher</title>
</head>
<body>
<h1>添加教师</h1>
<form method="post" action="/add-teacher/">
<p>教师名称:<input type="text" name="name"></p>
<input type="submit" value="提交">
</form>
</body>
</html>
edit_teacher.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>edit_teacher</title>
</head>
<body>
<h1>编辑教师</h1>
<form method="post" action="/edit-teacher/?nid={{ result.id }}">
<p>教师名称:<input type="text" value="{{ result.name }}" name="name"></p>
<input type="submit" value="提交">
</form>
</body>
</html>
part2 一对多操作
显示学生列表
与班级、教师相比,学生的数据库操作稍复杂一些:
"select student.id, student.`name`, class.title from student left JOIN class on student.class_id=class.id"
增加学生
学生所属班级信息以下拉框形式给用户,所以要将班级信息传给前端,数据库操作:
"select id, title from class"
前端:
<p>
所属班级:
<select name="class_id">
{% for row in class_list %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endfor %}
</select>
</p>
前端姓名和班级返回给后端,选中班级以 id
形式方便操作,写入数据库的语句:
"select id, title from class"
删除学生
与前面的无区别。
编辑学生
与之前类似,下拉框默认选择之根据当前学生的 class_id
确定,需要增加一个判断语句:
<select name="class_id">
{% for row in class_list %}
{% if row.id == student_info.class_id %}
<option selected value="{{ row.id }}">{{ row.title }}</option>
{% else %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endif %}
{% endfor %}
</select>
代码
path('students/', views.students),
path('add-student/', views.add_student),
path('del-student/', views.del_student),
path('edit-student/', views.edit_student),
由于反复相似操作,可以将常用步骤写成函数,简化代码使结构更清晰。
views.py
:
from utils import sqlhelper
def students(request):
"""
学生列表
:param request: 封装请求相关的所有信息
:return:
"""
student_list = sqlhelper.get_list("select student.id, student.`name`, class.title from student left JOIN class on student.class_id=class.id", [])
return render(request, 'students.html', {'student_list': student_list})
def add_student(request):
if request.method == 'GET':
class_list = sqlhelper.get_list("select id, title from class", [])
return render(request, 'add_student.html', {'class_list': class_list})
else:
name = request.POST.get('name')
class_id = request.POST.get('class_id')
sqlhelper.modify("insert into student(`name`, class_id) values(%s, %s)", [name, class_id, ])
return redirect('/students/')
def del_student(request):
nid = request.GET.get('nid')
sqlhelper.modify("delete from student where id=%s", [nid, ])
return redirect('/students/')
def edit_student(request):
if request.method == 'GET':
nid = request.GET.get('nid')
class_list = sqlhelper.get_list("select id, title from class",[])
student_info = sqlhelper.get_one("select id, name, class_id from student where id=%s", [nid, ])
return render(request, 'edit_student.html', {'class_list': class_list, 'student_info': student_info})
else:
nid = request.GET.get('nid')
name = request.POST.get('name')
class_id = request.POST.get('class_id')
sqlhelper.modify("update student set `name`=%s, class_id=%s where id=%s", [name, class_id, nid, ])
return redirect('/students/')
sqlhelper.py
:
import pymysql
def get_list(sql, args):
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute(sql, args)
list = cursor.fetchall()
cursor.close()
conn.close()
return list
def get_one(sql, args):
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute(sql, args)
item = cursor.fetchone()
cursor.close()
conn.close()
return item
def modify(sql, args):
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute(sql, args)
conn.commit()
cursor.close()
conn.close()
student.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>students</title>
</head>
<body>
<h1>学生列表</h1>
<div>
<a href="/add-student/">添加</a>
</div>
<table>
<thead>
<tr>
<th>id</th>
<th>学生姓名</th>
<th>所属班级</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in student_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
<td>{{ row.title }}</td>
<td>
<a href="/edit-student/?nid={{ row.id }}">编辑</a>
|
<a href="/del-student/?nid={{ row.id }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
add_student.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add-student</title>
</head>
<body>
<h1>添加学生</h1>
<form method="post" action="/add-student/">
<p>学生姓名:<input type="text" name="name"></p>
<p>
所属班级:
<select name="class_id">
{% for row in class_list %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endfor %}
</select>
</p>
<input type="submit" value="提交">
</form>
</body>
</html>
edit_student.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add-student</title>
</head>
<body>
<h1>编辑学生</h1>
<form method="post" action="/edit-student/?nid={{ student_info.id }}">
<p>学生姓名:<input type="text" name="name" value="{{ student_info.name }}"></p>
<p>
所属班级:
<select name="class_id">
{% for row in class_list %}
{% if row.id == student_info.class_id %}
<option selected value="{{ row.id }}">{{ row.title }}</option>
{% else %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endif %}
{% endfor %}
</select>
</p>
<input type="submit" value="提交">
</form>
</body>
</html>
part3 单表操作(对话框)
模态对话框
为区分接下来新开一个文件专门写模态对话框版本——
modal_classes.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>classes</title>
<style>
.hide {
display: none;
}
.shadow {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: black;
opacity: 0.4;
z-index: 999;
}
.modal {
position: fixed;
left: 50%;
top: 50%;
height: 300px;
width: 400px;
background-color: white;
margin-left: -200px;
margin-top: -150px;
z-index: 1000;
}
</style>
</head>
<body>
<h1>班级列表</h1>
<div>
<a onclick="showModal();">添加</a>
</div>
<table>
<thead>
<tr>
<th>id</th>
<th>班级名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in class_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.title }}</td>
<td>
<a href="/edit-class/?nid={{ row.id }}">编辑</a>
|
<a href="/del-class/?nid={{ row.id }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div id="shadow" class="shadow hide"></div>
<div id="modal" class="modal hide">
<form method="post" action="/modal-add-class/"> <!--转到add-class路径-->
<p>班级名称:<input type="text" name="title"></p> <!--返回数据的键为title-->
<input type="submit" value="提交">
</form>
</div>
<script>
function showModal() {
document.getElementById('shadow').classList.remove('hide');
document.getElementById('modal').classList.remove('hide');
}
</script>
</body>
</html>
urls.py
:
path('modal-classes/', modalviews.classes),
path('modal-add-class/', modalviews.add_class),
modalviews.py
:
def classes(request):
class_list = sqlhelper.get_list("select id, title from class", [])
return render(request, 'modal_classes.html', {'class_list': class_list})
def modal_add_class(request):
title = request.POST.get('title')
sqlhelper.modify("insert into class(title) values(%s)", [title, ])
return redirect('/classes/')
Form 表单提交后,页面一定会刷新。比如若修改函数返回值为 HttpResponse('ok')
,则页面显示 ‘ok’。
若想要保留原始输入内容,则不能用 Form 表单形式提交。
Ajax
取消表单,将输入信息以 Ajax 返回;
classes.html
:
<div id="shadow" class="shadow hide"></div>
<div id="modal" class="modal hide"><!--转到add-class路径-->
<p>班级名称:<input type="text" name="title" id="title"></p> <!--返回数据的键为title-->
<input type="button" value="提交" onclick="AjaxSend();">
</div>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js"></script>
<script>
function AjaxSend() {
$.ajax({
url: '/modal-add-class/',
type: 'POST',
data: {'title': $("#title").val()},
success: function (data) {
//当服务器处理完成智慧,返回数据时,该函数自动调用
//data=服务端返回的值
console.log(data)
if(data == "ok") {
alert('添加成功')
} else {
alert('添加失败')
}
}
})
}
</script>
modalviews.html
:
def add_class(request):
title = request.POST.get('title')
print(title)
if len(title) > 0:
sqlhelper.modify("insert into class(title) values(%s)", [title, ])
return HttpResponse('ok')
else:
return HttpResponse('not ok')
因为 Ajax 返回字符串,若想要添加班级成功后跳转刷新 classes/
页面,直接 return redirect('/classes/')
是不可行的;进行修改——
classes.html
:
<div id="modal" class="modal hide"><!--转到add-class路径-->
<p>班级名称:<input type="text" name="title" id="title"></p> <!--返回数据的键为title-->
<input type="button" value="提交" onclick="AjaxSend();">
<input type="button" value="取消" onclick="cancelModal();">
<span id="errormessage"></span>
</div>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js"></script>
<script>
function showModal() {
document.getElementById('shadow').classList.remove('hide');
document.getElementById('modal').classList.remove('hide');
}
function AjaxSend() {
$.ajax({
url: '/modal-add-class/',
type: 'POST',
data: {'title': $("#title").val()},
success: function (data) {
//当服务器处理完成智慧,返回数据时,该函数自动调用
//data=服务端返回的值
console.log(data)
if(data == "ok") {
location.href="/modal-classes"
} else {
$('#errormessage').text(data);
}
}
})
}
function cancelModal() {
document.getElementById('shadow').classList.add('hide');
document.getElementById('modal').classList.add('hide');
}
</script>
使后端能够返回错误信息显示在页面上:
modalviews.py
:
def add_class(request):
title = request.POST.get('title')
print(title)
if len(title) > 0:
sqlhelper.modify("insert into class(title) values(%s)", [title, ])
return HttpResponse('ok')
else:
return HttpResponse('标题不能为空')
模态对话框版班级操作(课后作业)
urls.py
:
path('modal-classes/', modalviews.classes),
path('modal-add-class/', modalviews.add_class),
path('modal-edit-class/', modalviews.edit_class),
path('modal-delete-class/', modalviews.delete_class),
modalviews.py
:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pymysql
from django.shortcuts import render, redirect, HttpResponse
from utils import sqlhelper
def classes(request):
class_list = sqlhelper.get_list("select id, title from class", [])
return render(request, 'modal_classes.html', {'class_list': class_list})
def add_class(request):
title = request.POST.get('title')
print(title)
if len(title) > 0:
sqlhelper.modify("insert into class(title) values(%s)", [title, ])
return HttpResponse('ok')
else:
return HttpResponse('标题不能为空')
def edit_class(request):
nid = request.POST.get('nid')
title = request.POST.get('title')
print(nid, title)
if len(title) > 0:
sqlhelper.modify("update class set title=%s where id=%s", [title, nid, ])
return HttpResponse('ok')
else:
return HttpResponse('标题不能为空')
def delete_class(request):
nid = request.POST.get('nid')
if nid != None:
sqlhelper.modify("delete from class where id=%s", [nid, ])
return HttpResponse('ok')
else:
return HttpResponse('失败')
modal_classes.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>classes</title>
<style>
.hide {
display: none;
}
.shadow {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: black;
opacity: 0.4;
z-index: 999;
}
.modal {
position: fixed;
left: 50%;
top: 50%;
height: 300px;
width: 400px;
background-color: white;
margin-left: -200px;
margin-top: -150px;
z-index: 1000;
}
</style>
</head>
<body>
<h1>班级列表</h1>
<div>
<a onclick="showAddModal();">添加</a>
</div>
<table>
<thead>
<tr>
<th>id</th>
<th>班级名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in class_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.title }}</td>
<td>
<a onclick="showEditModal({{ row.id }}, '{{ row.title }}');">编辑</a>
|
<a onclick="AjaxDelete({{ row.id }});">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div id="shadow" class="shadow hide"></div>
<div id="add-modal" class="modal hide"><!--转到add-class路径-->
<p>班级名称:<input type="text" name="title" id="add-title"></p> <!--返回数据的键为title-->
<input type="button" value="提交" onclick="AjaxSend();">
<input type="button" value="取消" onclick="cancelAddModal();">
<span id="add-errormessage"></span>
</div>
<div id="edit-modal" class="modal hide">
<input id="this-id" value="">
<p>班级名称:<input type="text" name="title" id="edit-title"></p> <!--返回数据的键为title-->
<input type="button" value="提交" onclick="AjaxEdit();">
<input type="button" value="取消" onclick="cancelEditModal();">
<span id="edit-errormessage"></span>
</div>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js"></script>
<script>
function showAddModal() {
document.getElementById('shadow').classList.remove('hide');
document.getElementById('add-modal').classList.remove('hide');
$('#add-errormessage').text('');
}
function AjaxSend() {
$.ajax({
url: '/modal-add-class/',
type: 'POST',
data: {'title': $("#add-title").val()},
success: function (data) {
//当服务器处理完成智慧,返回数据时,该函数自动调用
//data=服务端返回的值
console.log(data)
if(data == "ok") {
location.href="/modal-classes/"
} else {
$('#add-errormessage').text(data);
}
}
})
}
function cancelAddModal() {
document.getElementById('shadow').classList.add('hide');
document.getElementById('add-modal').classList.add('hide');
}
function showEditModal(nid, title) {
document.getElementById('shadow').classList.remove('hide');
document.getElementById('edit-modal').classList.remove('hide');
document.getElementById('edit-title').value = title;
document.getElementById('this-id').value = nid;
$('#edit-errormessage').text('');
}
function AjaxEdit(nid) {
console.log($('#this-id').val())
$.ajax({
url: '/modal-edit-class/',
type: 'POST',
data: {'nid': $('#this-id').val(), 'title': $('#edit-title').val()},
success: function (data) {
console.log(data)
if(data == "ok") {
location.href="/modal-classes/"
} else {
$('#edit-errormessage').text(data);
}
}
})
}
function cancelEditModal() {
document.getElementById('shadow').classList.add('hide');
document.getElementById('edit-modal').classList.add('hide');
}
function AjaxDelete(nid) {
$.ajax({
url: '/modal-delete-class/',
type: 'POST',
data: {'nid': nid},
success: function (data) {
if (data == 'ok') {
location.href = '/modal-classes/'
}else {
alert('失败')
}
}
})
}
</script>
</body>3
</html>
作业修改
使默认事件不执行:(增加 return)
<a href="www.baidu.com" onclick = "return modelEdit();">对话框编辑</a>
<script>
function modalEdit() {
alert(123);
return false;
}
</script>
编辑对话框:
<script>
function modalEdit(ths) {
document.getElementById('shadow').classList.remove('hide');
document.getElementById('editModal').classList.remove('hide');
/*
1. 获取当前点击标签
2. 当前标签父亲标签,再找其上方标签
3. 获取当前行班级名称,赋值到编辑对话框
*/
var row = $(ths).parent().prevAll();
var content = $(row[0]).text();
$('#editTitle').val(content);
var contentId = $(row[1]).text();
$('#editId').val(contentId);
</script>
修改函数:
def modal_edit_class(request):
ret = {'status': True, 'message': None}
try:
nid = request.POST.get('nid')
content = request.POST.get('content')
sqlhelper.modify("update class set title=%s where id=%s", [content, nid, ])
except Exception as e:
ret['status'] = False
ret['message'] = "处理异常"
import json
return HttpResponse(json.dumps(ret))
前端拿到数据的转换操作:
<script>
...
success:function(arg) {
// arg 字符串类型
// JSON.parse(字符串) => 对象
// JSON.stringfy(对象) => 字符串
arg = JSON.parse(arg);
if (arg.status) {
location.reload(); // 当前页面刷新
} else {
alert(arg.message);
}
}
</script>
小结
- 模态对话框
Form 表单提交,页面会刷新 - Ajax
jQuery
$.ajax({
url: ‘要提交的地址’,
type: ‘POST’, // 或 ‘GET’
data: {‘k1’: ‘v1’, ‘k2’: $(’#v2’).val()}, // 提交的数据
success: function(data) {
// 当服务端处理完毕后,自动执行的回调函数
// data是返回的数据
}
}) - 其他
1. 模板语言 if 条件语句
2. Form 表单提交,页面刷新
3. Ajax 提交,页面不刷新
4. js实现页面跳转:location.href = “跳转地址”
5. 两种方式
模态对话框(Ajax)如:登录
- 少量的输入框、下拉框
- 数据少
新URL方式 如:博客
- 操作多
- 数据大
part3 一对多操作(对话框)
内容概览
- 对话框 单表、一对多
- 多对多
- Bootstrap
- fontawesome
JS绑定JQuery绑定
增加学生
使用 jQuery 绑定,设置添加按钮的 id
:
<div>
<a id="addModal">添加</a>
</div>
对话框:
<div id="addModal" class="modal hide">
<h3>增加学生信息</h3>
<p>姓名:<input id="addName" type="text" name="name" placeholder="姓名"></p>
<p>班级:
<select id="addClassId">
{% for row in class_list %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endfor %}
</select>
</p>
<input id="btnAdd" type="button" value="提交">
<input type="button" value="取消">
<span id="addError" style="color: #ff0000"></span>
</div>
绑定事件:
<script>
$(function () {
$('#addModal').click(function () {
$('#shadow, #addModal').removeClass('hide');
});
$('#btnAdd').on("click", function () {
console.log('ok')
$.ajax({
url: '/modal-add-student/',
type: 'POST',
data: {'name': $('#addName').val(), 'class_id': $('#addClassId').val()},
success: function (arg) {
console.log(arg)
arg = JSON.parse(arg)
if (arg.status) {
location.reload()
} else {
$('#addError').text(arg.message)
}
}
})
});
});
</script>
编辑学生
另一种方式进行绑定(因为有多个,如果用 id
查找后面的会找不到):
<a class="btn-edit">编辑</a>
<script>
$('.btn-edit').click(function () {
$('#shadow, #editModal').removeClass('hide');
});
</script>
编辑学生如何保存 id
?
增加一行隐藏的 input
栏存放 id
:
<input id="editId" type="text" style="display: none">
编辑学生如何获取 class_id
?
一种方法是加一列隐藏的 <td>
存放 class_id
,另一种方式是为 class_title
增加自定义属性,值设为 class_id
。
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
<td clsId="{{ row.class_id }}">{{ row.title }}</td>
<script>
...
$('.btn-edit').click(function () {
$('#shadow, #editModal').removeClass('hide');
/*
1. 获取当前标签 $(this)
*/
var tds = $(this).parent().prevAll();
var studentId = $(tds[2]).text();
var studentName = $(tds[1]).text();
console.log(studentName);
var classId = $(tds[0]).attr('clsId');
console.log(studentId, studentName, classId);
$('#editId').val(studentId);
$('#editName').val(studentName);
$('#editClassId').val(classId);
});
</script>
通过属性进行绑定,则此处 $(this)
表示当前标签。
<script>
dataType: 'JSON', // 方法1
success: function (arg) {
JSON.parse(arg) // 方法2
</script>
删除学生
略
代码
urls.py
:
path('modal-students/', modalviews.students),
path('modal-add-student/', modalviews.add_student),
path('modal-edit-student/', modalviews.edit_student),
path('modal-delete-student/', modalviews.delete_student),
modalviews.py
:
def students(request):
student_list = sqlhelper.get_list("select student.id, student.`name`, student.class_id, class.title from student LEFT JOIN class on student.class_id=class.id", [])
class_list = sqlhelper.get_list("select id, title from class", [])
return render(request, 'modal_students.html', {'student_list': student_list, 'class_list': class_list})
def add_student(request):
ret = {'status': True, 'message': None}
try:
name = request.POST.get('name')
class_id = request.POST.get('class_id')
sqlhelper.modify("insert into student(name, class_id) values(%s, %s)", [name, class_id])
except Exception as e:
ret['status'] = False
ret['message'] = str(e)
return HttpResponse(json.dumps(ret))
def edit_student(request):
ret = {'status': True, 'message': None}
try:
nid = request.POST.get('nid')
name = request.POST.get('name')
class_id = request.POST.get('class_id')
sqlhelper.modify("update student set `name`=%s, class_id=%s where id=%s", [name, class_id, nid, ])
except Exception as e:
ret['status'] = False
ret['message'] = str(e)
return HttpResponse(json.dumps(ret))
def delete_student(request):
ret = {'status': True, 'message': None}
try:
nid = request.POST.get('nid')
sqlhelper.modify("delete from student where id=%s", [nid, ])
except Exception as e:
ret['status'] = False
ret['message'] = str(e)
return HttpResponse(json.dumps(ret))
modal_students.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>students</title>
<style>
.hide {
display: none;
}
.shadow {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: black;
opacity: 0.4;
z-index: 999;
}
.modal {
position: fixed;
left: 50%;
top: 50%;
height: 300px;
width: 400px;
background-color: white;
margin-left: -200px;
margin-top: -150px;
z-index: 1000;
}
</style>
</head>
<body>
<h1>学生列表</h1>
<div>
<a id="btn-add">添加</a>
</div>
<table>
<thead>
<tr>
<th>id</th>
<th>学生姓名</th>
<th>所属班级</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in student_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
<td clsId="{{ row.class_id }}">{{ row.title }}</td>
<td>
<a class="btn-edit">编辑</a>
|
<a class="btn-delete">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div id="shadow" class="shadow hide"></div>
<div id="addModal" class="modal hide">
<h3>增加学生信息</h3>
<p>姓名:<input id="addName" type="text" name="name" placeholder="姓名"></p>
<p>班级:
<select id="addClassId">
{% for row in class_list %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endfor %}
</select>
</p>
<input id="btnAdd" type="button" value="提交">
<input id="quitAdd" type="button" value="取消">
<span id="addError" style="color: #ff0000"></span>
</div>
<div id="editModal" class="modal hide">
<h3>编辑学生信息</h3>
<input id="editId" type="text" style="display: none">
<p>姓名:<input id="editName" type="text" name="name" placeholder="姓名"></p>
<p>班级:
<select id="editClassId">
{% for row in class_list %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endfor %}
</select>
</p>
<input id="btnEdit" type="button" value="提交">
<input id="quitEdit" type="button" value="取消">
<span id="editError" style="color: #ff0000"></span>
</div>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js"></script>
<script>
$(function () {
$('#btn-add').click(function () {
$('#shadow, #addModal').removeClass('hide');
$('#addError').text('')
});
$('#btnAdd').on("click", function () {
console.log('ok')
$.ajax({
url: '/modal-add-student/',
type: 'POST',
data: {'name': $('#addName').val(), 'class_id': $('#addClassId').val()},
success: function (arg) {
console.log(arg)
arg = JSON.parse(arg)
if (arg.status) {
location.reload()
} else {
$('#addError').text(arg.message)
}
}
})
});
$('#quitAdd').click(function () {
$('#shadow, #addModal').addClass('hide');
})
$('.btn-edit').click(function () {
$('#shadow, #editModal').removeClass('hide');
$('#editError').text('')
/*
1. 获取当前标签 $(this)
*/
var tds = $(this).parent().prevAll();
var studentId = $(tds[2]).text();
var studentName = $(tds[1]).text();
console.log(studentName);
var classId = $(tds[0]).attr('clsId');
console.log('id:', studentId, 'name:', studentName, 'class_id:', classId);
$('#editId').val(studentId);
$('#editName').val(studentName);
$('#editClassId').val(classId);
console.log('nid:', $('#editId').val(), 'name:', $('#editName').val(), 'class_id:', $('#editClassId').val())
});
$('#btnEdit').click(function () {
$.ajax({
url: '/modal-edit-student/',
type: 'POST',
data: {'nid': $('#editId').val(), 'name': $('#editName').val(), 'class_id': $('#editClassId').val()},
dataType: 'JSON', // 方法1
success: function (arg) {
//JSON.parse(arg) // 方法2
if (arg.status) {
location.reload();
} else {
$('#editError').text(arg.message);
}
}
})
});
$('#quitEdit').click(function () {
$('#shadow, #editModal').addClass('hide');
})
$('.btn-delete').click(function () {
var tds = $(this).parent().prevAll();
var nid = $(tds[2]).text();
$.ajax({
url: '/modal-delete-student/',
type: 'POST',
data: {'nid': nid},
dataType: 'JSON',
success: function (arg) {
if (arg.status) {
location.reload();
} else {
alert(arg.message);
}
}
})
})
});
</script>
</body>
</html>
part4 多对多操作
显示教师列表
数据库操作:
select teacher.id as tid, teacher.`name`, class.title from teacher
LEFT JOIN teacher2class on teacher2class.teacher_id=teacher.id
LEFT JOIN class on class.id=teacher2class.class_id;
这样获取到的数据(字典)是这样的:
[{'tid': 1, 'name': '张老师', 'title': 'C班'},
{'tid': 1, 'name': '张老师', 'title': 'B班'},
{'tid': 2, 'name': '李老师', 'title': 'D班'},
{'tid': 2, 'name': '李老师', 'title': 'A班'},
{'tid': 3, 'name': '王老师', 'title': 'C班'},
{'tid': 3, 'name': '王老师', 'title': 'B班'},
{'tid': 3, 'name': '王老师', 'title': 'A班'}]
我们需要将其整合:
result = {
# 1: {'name': xxx, 'tid': 1, 'titles': ['xxx', 'xxx']},
}
for row in teacher_list:
tid = row['tid']
if tid in result:
result[tid]['titles'].append(row['title'])
else:
result[tid]= {'tid': row['tid'], 'name': row['name'], 'titles': [row['title']]}
这样得到的数据就变成:
[1: {'tid': 1, 'name': '张老师', 'titles': ['C班', 'B班']},
2: {'tid': 2, 'name': '李老师', 'titles': ['D班', 'A班']},
3: {'tid': 3, 'name': '王老师', 'titles': ['C班', 'B班', 'A班']}]
前端的任课班级一栏再增加一个循环进行显示:
<table border="1">
<thead>
<tr>
<th>id</th>
<th>教师姓名</th>
<th>任课班级</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in teacher_list %}
<tr>
<td>{{ row.tid }}</td>
<td>{{ row.name }}</td>
<td>
{% for item in row.titles %}
<span style="display: inline-block; padding: 5px; border: 1px solid cadetblue;">{{ item }}</span>
{% endfor %}
</td>
<td>
<a>编辑</a>
|
<a>删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
增加教师
采用 url 跳转的方式。一个教师可以教授多个班级,所以使用复选框:
<body>
<h1>添加教师</h1>
<form method="post" action="/add-teacher/">
<p>教师名称:<input type="text" name="name"></p>
<p>任教班级:
<select multiple size="5" name="class_ids">
{% for item in class_list %}
<option value="{{ item.id }}">{{ item.title }}</option>
{% endfor %}
</select>
</p>
<input type="submit" value="提交">
</form>
</body>
后台以 getlist
的方式获取 class_ids
列表:
class_ids = request.POST.getlist('class_ids')
增加教师信息需要改动两个表—— teacher
表和 teaccher2class
表。先在老师表中添加一条数据,再在老师班级关系表中插入数据,因此需要获取新增老师的 id
,考虑增加一种具有返回值的 sqlhelper
函数:
def create(sql, args):
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute(sql, args)
conn.commit()
last_row_id = cursor.lastrowid
cursor.close()
conn.close()
return last_row_id
插入数据时,若采用循环方式,如:
for class_id in class_ids:
sqlhelper.modify("insert into teacher2class(teacher_id, class_id) values(%s, %s)", [teacher_id, class_id])
会反复连接、提交和关闭数据库,十分耗时。因此对 sqlhelper
进行修改。设置一个 SqlHelper
类,以类的方式,对公共的操作进行封装:
class SqlHelper(object):
def __init__(self):
# 读取配置文件
self.connect()
@staticmethod
def connect(self):
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test') # 可以以配置文件方式
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
def get_list(self, sql, args):
self.cursor.execute(sql, args)
list = self.cursor.fetchall()
return list
def get_one(self, sql, args):
self.cursor.execute(sql, args)
item = self.cursor.fetchone()
return item
def modify(self, sql, args):
self.cursor.execute(sql, args)
self.conn.commit()
def multiple_modify(self, sql, args):
self.cursor.executemany(sql, args)
self.conn.commit()
def create(self, sql, args):
self.cursor.execute(sql, args)
self.conn.commit()
return self.cursor.lastrowid
def close(self):
self.cursor.close()
self.conn.close()
这样就可以一次性提交数据:
data_list = []
for class_id in class_ids:
temp = (teacher_id, class_id)
data_list.append(temp)
obj = sqlhelper.SqlHelper()
obj.multiple_modify("insert into teacher2class(teacher_id, class_id) values (%s, %s)", data_list)
obj.close()
编辑教师
与 url 跳转方式编辑学生相似。在任教班级的默认显示上,需要将获取到的 class_id_list
中对应的班级设为选中,而通过
class_id_list = obj.get_list("select teacher_id, class_id from teacher2class where teacher_id=%s", [nid, ])
获取到的数据形式为:
[{'class_id': 1}, {'class_id': 4}]
为了方便需要将其转换形式:
temp = []
for i in class_id_list:
temp.append(i['class_id'])
print(temp)
这样得到的数据形式为:
[1, 4]
在 html 中利用循环将列表中 id
对应的班级设为 selected
即可。
更新老师班级关系表时有两种方法:·
- 删除该老师原来任教的所有班级数据,再将新数据写入。这种方法简单,但效率较低;
- 将新数据与原来的进行匹配,然后进行增加和删除。这种方法效率更高。
代码
views.py
:
def teachers(request):
teacher_list = sqlhelper.get_list('''
select teacher.id as tid, teacher.`name`, class.title from teacher
LEFT JOIN teacher2class on teacher2class.teacher_id=teacher.id
LEFT JOIN class on class.id=teacher2class.class_id;
''', [])
print(teacher_list)
result = {
# 1: {'name': xxx, 'tid': 1, 'titles': ['xxx', 'xxx']},
}
for row in teacher_list:
tid = row['tid']
if tid in result:
result[tid]['titles'].append(row['title'])
else:
result[tid]= {'tid': row['tid'], 'name': row['name'], 'titles': [row['title']]}
print(result.values())
return render(request, 'teachers.html', {'teacher_list': result.values()})
def add_teacher(request):
if request.method == 'GET':
class_list = sqlhelper.get_list("select id, title from class", [])
return render(request, 'add_teacher.html', {'class_list': class_list})
else:
name = request.POST.get('name')
class_ids = request.POST.getlist('class_ids')
print(name, class_ids)
# 在老师表中添加一条数据
teacher_id = sqlhelper.create("insert into teacher(`name`) values(%s)", [name,])
# 在老师班级关系表中插入数据
# 首先调整数据形式
data_list = [
# (1, 1)
]
# 一次性提交数据
for class_id in class_ids:
temp = (teacher_id, class_id)
data_list.append(temp)
obj = sqlhelper.SqlHelper()
obj.multiple_modify("insert into teacher2class(teacher_id, class_id) values (%s, %s)", data_list)
obj.close()
return redirect('/teachers/')
def edit_teacher(request):
if request.method == 'GET':
nid = request.GET.get('nid')
obj = sqlhelper.SqlHelper()
print(nid)
teacher_info = obj.get_one("select id, `name` from teacher where id=%s", [nid, ])
class_id_list = obj.get_list("select class_id from teacher2class where teacher_id=%s", [nid, ])
class_list = obj.get_list("select id, title from class", [])
obj.close()
print(teacher_info, class_id_list)
temp = []
for i in class_id_list:
temp.append(i['class_id'])
print(temp)
return render(request, 'edit_teacher.html', {
'teacher_info': teacher_info,
'class_id_list': temp,
'class_list': class_list
})
else:
nid = request.GET.get('nid')
name = request.POST.get('name')
class_ids = request.POST.getlist('class_ids')
print(nid, name, class_ids)
obj = sqlhelper.SqlHelper()
# 更新老师表
obj.modify("update teacher set `name`=%s where id=%s", [name, nid, ])
# 更新老师班级关系表
obj.modify("delete from teacher2class where teacher_id=%s", [nid, ])
data_list = []
for class_id in class_ids:
temp = (nid, class_id)
data_list.append(temp)
print(data_list)
obj.multiple_modify("insert into teacher2class(teacher_id, class_id) values(%s, %s)", data_list)
obj.close()
return redirect('/teachers/')
def delete_teacher(request):
nid = request.GET.get('nid')
obj = sqlhelper.SqlHelper()
obj.modify("delete from teacher where id=%s", [nid, ])
obj.modify("delete from teacher2class where teacher_id=%s", [nid, ])
return redirect('/teachers/')
teachers.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>teachers</title>
</head>
<body>
<h1>教师列表</h1>
<a href="/add-teacher/">添加</a>
<table border="1">
<thead>
<tr>
<th>id</th>
<th>教师姓名</th>
<th>任教班级</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in teacher_list %}
<tr>
<td>{{ row.tid }}</td>
<td>{{ row.name }}</td>
<td>
{% for item in row.titles %}
<span style="display: inline-block; padding: 5px; border: 1px solid cadetblue;">{{ item }}</span>
{% endfor %}
</td>
<td>
<a href="/edit-teacher/?nid={{ row.tid }}">编辑</a>
|
<a href="/delete-teacher/?nid={{ row.tid }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
add_teacher.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add-teacher</title>
</head>
<body>
<h1>添加教师</h1>
<form method="post" action="/add-teacher/">
<p>教师名称:<input type="text" name="name"></p>
<p>任教班级:
<select multiple size="5" name="class_ids">
{% for item in class_list %}
<option value="{{ item.id }}">{{ item.title }}</option>
{% endfor %}
</select>
</p>
<input type="submit" value="提交">
</form>
</body>
</html>
edit_teacher.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>edit-teacher</title>
</head>
<body>
<h1>编辑教师</h1>
<form method="post" action="/edit-teacher/?nid={{ teacher_info.id }}">
<p>教师名称:<input type="text" value="{{ teacher_info.name }}" name="name"></p>
<p>任教班级:
<select multiple size="5" name="class_ids">
{% for item in class_list %}
{% if item.id in class_id_list %}
<option value="{{ item.id }}" selected>{{ item.title }}</option>
{% else %}
<option value="{{ item.id }}">{{ item.title }}</option>
{% endif %}
{% endfor %}
</select>
</p>
<input type="submit" value="提交">
</form>
</body>
</html>
小结
-
Http 请求生命周期
请求头 -> 提取 URL -> 路由关系匹配 -> 函数(模板 + 渲染) -> 返回用户(响应头 + 响应体) -
render 会对页面进行渲染,即替换。
-
模板的渲染是在后台执行的。
一个例子:
后端:def function(request): render(request, 'example.html', {'k1': 1, 'k2': 'uuu'})
前端:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <h1>{{ k1 }}</h1> <h1>{{ k2 }}</h1> <script> alert(); </script> </body> </html>
若是
alert({{ k1 }});
,则页面弹出警告框,内容为 “1”;
若是alert({{ k2 }});
,则会出现报错,uuu is not defined
。因为经过替换后代码变为alert(uuu);
,而uuu
并没有定义。因此若想要警告框显示 “uuu”,应该写成alert('{{ k2 }}');
。
- HTML
for
if
索引
{{ }} - js 序列化 & 反序列化
- 阻止默认事件发生:
onclick 事件绑定: <a οnclick=‘return func();’></a> 同时函数里 return false;
jQuery 方式绑定: <a id></a> 函数里 return false;
part5 多对多操作(对话框)
增加教师
为了避免函数直接写在一起太凌乱,可以如下进行绑定:
<script>
$(function () {
bindAdd();
});
function bindAdd() {
...
}
</script>
点击“添加”按钮后,向后端获取 class_list
来显示。动态添加方法:
<script>
...
$.ajax({
url: '/get-all-class/',
type: 'GET',
dataType: 'JSON',
success: function (arg) {
console.log(arg)
/*
0: {id: 1, title: "A班"}
1: {id: 2, title: "B班"}
2: {id: 3, title: "C班"}
3: {id: 4, title: "D班"}
*/
$.each(arg, function (i, row) {
var tag = document.createElement('option');
tag.innerText = row.title;
tag.setAttribute('value', row.id);
$('#addClassIds').append(tag);
})
}
})
</script>
对于需要时间加载数据的功能,为了更好的用户体验,可以先显示一个加载符号,当后端数据传送过来之后再显示对话框:
<style>
.loading {
position: fixed;
width: 200px;
height: 150px;
left: 50%;
top: 50%;
margin-left: -200px;
margin-top: -100px;
background-image: url("/static/images/loading.gif");
z-index: 10001;
}
</style>
<div id="loading" class="loading hide"></div>
<script>
$('#shadow, #loading').removeClass('hide');
...
$('#loading').addClass('hide');
$('#addModal').removeClass('hide');
</script>
注意,当 ajax 向后端传递数据为列表形式时,需要加上 traditional: true,
。
编辑教师
在 python 中可以直接用 in 判断一个数据是否在列表中,而在 JavaScript 中,可以通过 indexOf
:
v = [11, 22, 33]
v.indexOf(22) = 1
v.indexOf(222) = -1
若返回 -1,则代表不存在。
代码
modalviews.py
:
def teachers(request):
teacher_list = sqlhelper.get_list('''
select teacher.id as tid, teacher.`name`, class.title from teacher
LEFT JOIN teacher2class on teacher2class.teacher_id=teacher.id
LEFT JOIN class on class.id=teacher2class.class_id;
''', [])
print(teacher_list)
result = {
# 1: {'name': xxx, 'tid': 1, 'titles': ['xxx', 'xxx']},
}
for row in teacher_list:
tid = row['tid']
if tid in result:
result[tid]['titles'].append(row['title'])
else:
result[tid] = {'tid': row['tid'], 'name': row['name'], 'titles': [row['title']]}
print(result.values())
return render(request, 'modal_teachers.html', {'teacher_list': result.values()})
def add_teacher(request):
ret = {'status': True, 'message': None}
try:
name = request.POST.get('name')
class_id_list = request.POST.getlist('class_id_list')
obj = sqlhelper.SqlHelper()
teacher_id = obj.create("insert into teacher(`name`) values(%s)", [name, ])
data_list = []
for class_id in class_id_list:
temp = (teacher_id, class_id)
data_list.append(temp)
obj.multiple_modify("insert into teacher2class(teacher_id, class_id) values(%s, %s)", data_list)
obj.close()
except Exception as e:
ret['status'] = False
ret['message'] = str(e)
return HttpResponse(json.dumps(ret))
def delete_teacher(request):
ret = {'status': True, 'message': None}
try:
nid = request.POST.get('nid')
obj = sqlhelper.SqlHelper()
obj.modify("delete from teacher where id=%s", [nid, ])
obj.modify("delete from teacher2class where teacher_id=%s", [nid, ])
obj.close()
except Exception as e:
ret['status'] = False
ret['message'] = str(e)
return HttpResponse(json.dumps(ret))
def edit_teacher(request):
ret = {'status': True, 'message': None}
try:
nid = request.POST.get('tid')
name = request.POST.get('name')
class_ids = request.POST.getlist('class_id_list')
print('class_id_list', class_ids)
obj = sqlhelper.SqlHelper()
obj.modify("update teacher set `name`=%s where id=%s", [name, nid, ])
obj.modify("delete from teacher2class where teacher_id=%s", [nid, ])
data_list = []
for class_id in class_ids:
temp = (nid, class_id)
data_list.append(temp)
obj.multiple_modify("insert into teacher2class(teacher_id, class_id) values(%s, %s)", data_list)
obj.close()
except Exception as e:
ret['status'] = False
ret['message'] = str(e)
return HttpResponse(json.dumps(ret))
# utils 部分
def get_all_class_and_selected(request):
nid = request.POST.get('nid')
obj = sqlhelper.SqlHelper()
class_list = obj.get_list("select id, title from class", [])
class_id_list = obj.get_list("select class_id from teacher2class where teacher_id=%s", [nid, ])
obj.close()
class_ids = []
for i in class_id_list:
class_ids.append(i['class_id'])
result = [class_list, class_ids]
print(result)
return HttpResponse(json.dumps(result))
modal_teachers.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>teachers</title>
<style>
.hide {
display: none;
}
.shadow {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: black;
opacity: 0.4;
z-index: 999;
}
.loading {
position: fixed;
width: 200px;
height: 150px;
left: 50%;
top: 50%;
margin-left: -200px;
margin-top: -100px;
background-image: url("/static/images/loading.gif");
z-index: 10001;
}
.modal {
position: fixed;
left: 50%;
top: 50%;
height: 300px;
width: 300px;
background-color: white;
margin-left: -200px;
margin-top: -150px;
z-index: 1000;
}
</style>
</head>
<body>
<h1>教师列表</h1>
<a id="btn-add">添加</a>
<table border="1">
<thead>
<tr>
<th>id</th>
<th>教师姓名</th>
<th>任课班级</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in teacher_list %}
<tr>
<td>{{ row.tid }}</td>
<td>{{ row.name }}</td>
<td>
{% for item in row.titles %}
<span style="display: inline-block; padding: 5px; border: 1px solid cadetblue;">{{ item }}</span>
{% endfor %}
</td>
<td>
<a class="btn-edit">编辑</a>
|
<a class="btn-delete">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div id="shadow" class="shadow hide"></div>
<div id="loading" class="loading hide"></div>
<div id="addModal" class="modal hide">
<h3>增加教师信息</h3>
<p>教师姓名:<input id="addName" type="text" name="name" placeholder="姓名"></p>
<p>任教班级:
<select id="addClassIds" multiple size="5"></select>
</p>
<input id="btnAdd" type="button" value="提交">
<input id="quitAdd" type="button" value="取消">
<span id="addError" style="color: #ff0000"></span>
</div>
<div id="editModal" class="modal hide">
<h3>编辑教师信息</h3>
<input id="edit_tid" value="" type="hidden">
<p>教师姓名:<input id="editName" type="text" name="name"></p>
<p>任教班级:
<select id="editClassIds" multiple size="5"></select>
</p>
<input id="btnEdit" type="button" value="提交">
<input id="quitEdit" type="button" value="取消">
<span id="editError" style="color: #ff0000"></span>
</div>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.12.4.min.js"></script>
<script>
$(function () {
bindAdd();
bindAddSubmit();
bindDelete();
bindEdit();
bindEditSubmit();
bindQuit();
});
function bindAdd() {
$('#btn-add').click(function () {
console.log('ok');
$('#shadow, #loading').removeClass('hide');
$('#addClassIds').empty();
$.ajax({
url: '/get-all-class/',
type: 'GET',
dataType: 'JSON',
success: function (arg) {
console.log(arg);
/*
0: {id: 1, title: "A班"}
1: {id: 2, title: "B班"}
2: {id: 3, title: "C班"}
3: {id: 4, title: "D班"}
*/
$.each(arg, function (i, row) {
var tag = document.createElement('option');
tag.innerText = row.title;
tag.setAttribute('value', row.id);
$('#addClassIds').append(tag);
});
$('#loading').addClass('hide');
$('#addModal').removeClass('hide');
}
});
});
}
function bindAddSubmit() {
$('#btnAdd').click(function () {
var name = $('#addName').val();
var class_id_list = $('#addClassIds').val();
console.log(name, class_id_list);
$.ajax({
'url': '/modal-add-teacher/',
type: 'POST',
data: {'name': name, 'class_id_list': class_id_list},
dataType: 'JSON',
traditional: true, // 提交的数据有列表
success: function (arg) {
console.log(arg);
if(arg.status) {
location.reload();
} else {
$('#addError').text(arg.message);
}
}
});
});
}
function bindDelete() {
$('.btn-delete').click(function () {
var tds = $(this).parent().prevAll();
var nid = $(tds[2]).text();
console.log(nid);
$.ajax({
url: '/modal-delete-teacher/',
type: 'POST',
data: {'nid': nid},
dataType: 'JSON',
success: function (arg) {
if(arg.status) {
location.reload();
} else {
alert(arg.message);
}
}
})
});
}
function bindEdit() {
$('.btn-edit').click(function () {
$('#shadow, #loading').removeClass('hide');
$('#editClassIds').empty();
var tds = $(this).parent().prevAll();
var nid = $(tds[2]).text();
var name = $(tds[1]).text();
$.ajax({
url: '/get-all-class-and-selected/',
type: 'POST',
data: {'nid': nid},
dataType: 'JSON',
success: function (arg) {
console.log(arg);
var class_list = arg[0];
var class_ids = arg[1];
$.each(class_list, function (i, row) {
var tag = document.createElement('option');
tag.innerText = row.title;
tag.setAttribute('value', row.id);
if(class_ids.indexOf(row.id) >= 0)
tag.setAttribute('selected', true);
$('#editClassIds').append(tag);
});
$('#loading').addClass('hide');
$('#editModal').removeClass('hide');
$('#edit_tid').val(nid);
$('#editName').val(name);
}
});
});
}
function bindEditSubmit() {
$('#btnEdit').click(function () {
var tid = $('#edit_tid').val();
var name = $('#editName').val();
var class_id_list = $('#editClassIds').val();
console.log(name, class_id_list);
$.ajax({
'url': '/modal-edit-teacher/',
type: 'POST',
data: {'tid': tid, 'name': name, 'class_id_list': class_id_list},
dataType: 'JSON',
traditional: true, // 提交的数据有列表
success: function (arg) {
console.log(arg);
if(arg.status) {
location.reload();
} else {
$('#editError').text(arg.message);
}
}
});
})
}
function bindQuit() {
$('#quitAdd').click(function () {
$('#shadow, #addModal').addClass('hide');
});
$('#quitEdit').click(function () {
$('#shadow, #editModal').addClass('hide');
});
}
</script>
</body>
</html>