文章目录
一、Django连接数据库
在之前的文章我们有说到过,django的数据库默认初始配置是使用sqlite数据库的,要想使用mysql作为数据库,需在settings.py中改变连接配置信息。
mysql配置及安装详情:点击查看mysql详细配置。
二、原生sql操作数据库
使用Django来操作MySQL时,底层还是通过Python来操作的,因此要想用Django来操作MySQL,首先需要安装驱动程序。
在Python3中,驱动程序有多种选择,包括pymysql、mysqlclient等。
如果已经按照上面文章配置完毕后,是可以导入pymysql的,所以这里我们就使用pymysql进行操作。
1.表结构的设计
在这篇文章中,我们将通过案例的方式来使用pymysql,而我们需要做的案例是学员管理系统,和做项目是一样的,表结构设计永远都是第一步,那么做学员管理系统,首先我们要想,肯定是要有班级,老师及学生的,且老师可以教多个班级
,班级和学生要关联起来,老师和班级也要关联起来,但是考虑到老师可以任教多个班级,所以老师和班级的关系表需在多创建一张表。
首先先创建一个数据库xxx:
create database xxx
在创建class表:
CREATE TABLE class(
id INT PRIMARY KEY auto_increment,
title VARCHAR(20)
)
在创建学生表:
CREATE TABLE Student(
id INT PRIMARY KEY AUTO_INCREMENT,
stu_name CHAR(20) NOT NULL,
class_id INT,
FOREIGN KEY(class_id) REFERENCES Class(id) ON DELETE CASCADE ON UPDATE CASCADE
)CHARSET utf8;
在创建老师表:
CREATE TABLE Teacher(
id INT PRIMARY KEY auto_increment,
th_name CHAR(20) NOT NULL
)charset utf8;
最后在创建老师和班级的关联表:
CREATE TABLE teachers(
id INT PRIMARY KEY auto_increment,
t_id INT,
c_id INT,
FOREIGN KEY(t_id) REFERENCES Teacher(id) on delete cascade on update cascade,
FOREIGN KEY(c_id) REFERENCES Class(id) on delete cascade on update cascade
)charset utf8;
表结构设计完成后,我们就可以进行下一步的操作了。
2.pymysql操作数据库
通过上述操作对mysql创建表成功后,我们就可以进行添加操作了,为了方便演示pymysql是怎么操作的,这里就以班级表进行添加操作。
不管是使用pymysql或者是mysqlclient或者是mysqldb,接口都是一样的。
Python DB API
规范下cursor对象常用接口如下:
接口 | 含义 |
---|---|
description | 如果cursor执行了SQL语句,那么执行cursor.description属性会返回一个列表,这个列表中装的是元组,元组中装的分别是(name,type_code,display_size,internal_size,precision,scale,null_ok) ,其中name代表的是查找出来的数据的字段名称。 |
rowcount | 代表的是在执行了SQL语句后受影响的行数。 |
close | 关闭游标,关闭游标以后就再也不能使用了,否则会抛出异常。 |
execute(sql[,parameters]) | 执行SQL语句,还可以根据需要传递参数,定义parameters属性即可。 |
fetchone | 在执行了查询操作以后,获取第一条数据。 |
fetchmany(size) | 在执行查询操作以后,获取多条数据,具体是多少条要看传的size参数,如果不传size参数,那么默认是获取第一条数据。 |
fetchall | 获取所有满足sql语句的数据。 |
commit | 提交添加数据到数据库 |
首先在根目录创建一个app01的文件夹之后在创建一个views.py来存放我们后面操作的代码。
urls.py如下:
from django.urls import path
from app01 import views
urlpatterns = [
path('add_class/', views.add_class, name='add_class'),
]
app01/views.py如下:
from django.shortcuts import render, HttpResponse
import pymysql
def add_class(request):
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='xxx')
# 转换成字典类型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("INSERT INTO class(teacher_name) VALUES (%s)", ['全栈1班', ])
conn.commit()
cursor.execute("select * from class", [])
classes = cursor.fetchall()
print(classes)
cursor.close()
conn.close()
return HttpResponse('ok')
此时访问http://127.0.0.1:8000/add_class/,控制台打印:
[{'id': 1, 'teacher_name': '全栈1班'}]
3.数据库连接优化
通过上述代码,我们可以发现,当我们每次执行一次视图函数都会建立起连接和关闭连接,反反复复,在人流量较大的情况下,会给数据库造成很大的压力,因此为了防止数据库反复建立、断开连接及代码优化,我们可以定义一个类,需要时在调用。
新建文件夹SQL_connection/sqlheper.py如下:
import pymysql
class SqlHelper(object):
def __init__(self):
self.conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='xxx')
self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)
# 获取多个
def get_list(self, sql, args):
self.cursor.execute(sql, args)
result_list = self.cursor.fetchall()
return result_list
# 获取单个
def get_one(self, sql, args):
self.cursor.execute(sql, args)
result = self.cursor.fetchone()
return result
# 添加、删除不返回方法
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()
# 添加、删除返回id操作
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()
app01/views.py如下:
from django.shortcuts import render, HttpResponse
from SQL_connection.sqlheper import SqlHelper
def add_class(request):
nid = '全栈4班'
obj = SqlHelper()
obj.modify("INSERT INTO class(teacher_name) VALUES (%s)", [nid, ])
data = obj.get_list('select * from class', [])
print(data)
obj.close()
return HttpResponse('ok')
此时访问http://127.0.0.1:8000/add_class/,控制台打印:
[{'id': 1, 'teacher_name': '全栈一班'},{'id': 2, 'teacher_name': '全栈4班'}]
显然我们可以发现代码更加的整洁,且也不用在数据库反复的进行连接操作了。
三、案例-学员管理系统
使用原生SQL方式实现一个学员管理系统,完成图书的增删查和前端页面展示。
1.班级列表
一、班级首页
urls.py如下:
from django.urls import path
from app01 import views
urlpatterns = [
path('add_class/', views.add_class, name='add_class'),
path('classes/', views.classes, name='classes')
]
app01/views.py如下:
from django.shortcuts import render, HttpResponse
from SQL_connection.sqlheper import SqlHelper
def classes(request):
obj = SqlHelper()
class_list = obj.get_list("select * from class", [])
return render(request, 'classes.html', {'class_list': class_list})
classes.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>班级列表</h1>
<a href="#">添加班级</a>
<table>
<thead>
<tr>
<th>ID</th>
<th>班级名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in class_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ row.title }}</td>
<td>
<a href="#">编辑</a>
|
<a href="#">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
此时访问127.0.0.1:8000/classes/如下:
显然我们之前创建的班级列表全部都显示出来了。
二、班级添加
由于我们已经封装好了一个类,所以如果想添加班级,只需要在添加一个路由、视图函数、保存、跳转。 由此:
- 添加一个路由
- 视图函数
- 保存数据到数据库
- 跳转到班级页面
因为之前的示例添加和班级表添加类似,所以只需修改一下就可以当作班级添加使用了。
urls.py如下:
from django.urls import path
from app01 import views
urlpatterns = [
path('add_class/', views.add_class, name='add_class'),
path('classes/', views.classes, name='classes')
]
add_class.html:如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>班级添加</h1>
<form action="{% url 'add_class' %}" method="post">
{% csrf_token %}
<p>班级名称:<input type="text" name="title"></p>
<input type="submit" value="提交" />
</form>
</body>
</html>
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def add_class(request):
if request.method == "GET":
return render(request, 'add_class.html')
# post请求
nid = request.POST.get('title')
obj = SqlHelper()
obj.modify("INSERT INTO class(title) VALUES (%s)", [nid, ])
obj.close()
return redirect('classes')
classes.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>班级列表</h1>
<a href="{% url 'add_class' %}">添加班级</a>
<table>
<thead>
<tr>
<th>ID</th>
<th>班级名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in class_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ row.title }}</td>
<td>
<a href="#">编辑</a>
|
<a href="#">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
此时访问127.0.0.1:8000/classes/如下:
显然,视图函数执行了post请求并成功的保存到数据库,进行跳转页面。
三、班级删除
班级的删除和添加有点不一样,因为如果想要删除一个班级,我们必须知道他的一个条件,而拿什么条件会更好呢,我们一般会拿id,因为id是唯一的,不会重复,所以我们可以通过获取到在url里加上一个get请求参数、创建路由、视图函数、跳转。
- 在班级首页删除a标签的url里加上一个get参数
(参数为id)
- 创建删除视图函数
- 删除成功跳转到班级首页
urls.py如下:
from django.urls import path
from app01 import views
urlpatterns = [
path('add_class/', views.add_class, name='add_class'),
path('classes/', views.classes, name='classes'),
path('del_class/', views.del_class, name='del_class'),
]
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def del_class(request):
obj = SqlHelper()
nid = request.GET.get('class_id')
obj.modify('delete from class where id=%s', [nid])
obj.close()
return redirect('classes')
classes.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>班级列表</h1>
<a href="{% url 'add_class' %}">添加班级</a>
<table>
<thead>
<tr>
<th>ID</th>
<th>班级名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in class_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ row.title }}</td>
<td>
<a href="#">编辑</a>
|
<a href="{% url 'del_class' %}?class_id={{ row.id }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
此时访问127.0.0.1:8000/classes/如下:
如上述所属,点击删除后,数据将在数据库删除后展示在班级页面上。
四、班级编辑
班级的编辑操作和班级删除类似,不过班级的编辑操作,需要点击a标签编辑,需要编辑的内容需显示出来,且还要携带相应的id。所以在发送get请求的时候我们需要获取要编辑的班级的id、获取到id后通过数据库查询获取修改内容,在把获取到的值传给后台的模板进行渲染,展示。
- 创建编辑路由
- 创建编辑的视图函数
- 通过get的方式传id给后台
- 通过id向数据库查询修改内容
点击编辑标签显示编辑的内容
- post请求成功后通过id作为条件、内容修改班级
- 跳转到班级页面
urls.py如下:
from django.urls import path
from app01 import views
urlpatterns = [
path('add_class/', views.add_class, name='add_class'),
path('classes/', views.classes, name='classes'),
path('del_class/', views.del_class, name='del_class'),
path('edit_class/', views.edit_class, name='edit_class'),
]
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def edit_class(request):
obj = SqlHelper()
if request.method == "GET":
nid = request.GET.get('class_id')
class_dict = obj.get_one('select id,title from class where id=%s', [nid, ])
obj.close()
return render(request, 'edit_class.html', {'class_dict': class_dict})
nid = request.GET.get('nid')
title = request.POST.get('title')
obj.modify('update class set title=%s where id=%s', [title, nid, ])
obj.close()
return redirect('classes')
edit_class.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>班级编辑</h1>
<form action="{% url 'edit_class' %}?nid={{ class_dict.id }}" method="post">
{% csrf_token %}
<p>班级名称:<input type="text" name="title" value="{{ class_dict.title }}"></p>
<input type="submit" value="提交">
</form>
</body>
</html>
classes.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>班级列表</h1>
<a href="{% url 'add_class' %}">添加班级</a>
<table>
<thead>
<tr>
<th>ID</th>
<th>班级名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in class_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ row.title }}</td>
<td>
<a href="{% url 'edit_class' %}?class_id={{ row.id }}">编辑</a>
|
<a href="{% url 'del_class' %}?class_id={{ row.id }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
此时访问127.0.0.1:8000/classes/如下:
可以看到,get请求通过获取id来展示修改内容,而post请求通过获取的id作为条件
去修改班级名称。
2.学生列表
一、学生首页
自此班级列表的展示就已经完成了,学生列表和班级列表类似,所以这里就直接将学生相应所需的视图函数、路由、模板写上,后面再进行相应操作。
因为现在还没有添加学生成员,为了看效果,我们主动在数据库添加两位学生,方便展示。
数据库增加两名学生(这里条件的id填你班级的id
):
INSERT INTO student(stu_name,class_id) VALUES('小红',7)
INSERT INTO student(stu_name,class_id) VALUES('小蓝',6)
urls.py如下:
from django.urls import path
from app01 import views
urlpatterns = [
# 班级列表
path('add_class/', views.add_class, name='add_class'),
path('classes/', views.classes, name='classes'),
path('del_class/', views.del_class, name='del_class'),
path('edit_class/', views.edit_class, name='edit_class'),
# 学生列表
path('students/', views.students, name='students'),
path('add_student/', views.add_student, name='add_student'),
path('del_student/', views.del_student, name='del_student'),
path('edit_student/', views.edit_student, name='edit_student'),
]
students.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>学生列表</h1>
<a href="{% url 'add_student' %}">添加学生</a>
<table>
<thead>
<tr>
<th>ID</th>
<th>学生名称</th>
<th>班级</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in student_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ row.stu_name }}</td>
<td>{{ row.title }}</td>
<td>
<a href="{% url 'edit_student' %}?student_id={{ row.id }}">编辑</a>
|
<a href="{% url 'del_student' %}?student_id={{ row.id }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def students(request):
obj = SqlHelper()
student_list = obj.get_list(
"SELECT stu.id,stu.`stu_name`,class_id,title FROM student AS stu INNER JOIN class AS cls ON stu.`class_id`=cls.`id`",
[])
obj.close()
print(student_list)
return render(request, 'students.html', {'student_list': student_list})
def add_student(request):
return render(request, 'add_student.html')
def del_student(request):
return redirect('students')
def edit_student(request):
return render(request, 'edit_student.html')
此时访问127.0.0.1:8000/students/如下:
此时插入的学生列表的数据就全部的展示出来了。
二、学生添加
学生列表展示完成后,就需要给学生做添加处理,学生添加的方法也和班级添加的方法类似,只需修改一些条件,给学生列表的添加附上添加路由,给url做上视图、模板、返回到学生列表即可,因为学生班级需要选择,所以在视图中还需要获取所有的班级列表。
- 获取班级列表
- 通过get请求展示界面
- 通过post请求获取增加的值(
获取班级id需要select标签的name属性即可获取
) - 在添加视图中做sql查询增加操作
- 添加成功跳转会学生列表
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def add_student(request):
if request.method == "GET":
obj = SqlHelper()
class_list = obj.get_list('select id,title from class', [])
return render(request, 'add_student.html', {'class_list': class_list})
# post请求
title = request.POST.get('title')
class_id = request.POST.get('class_id')
obj = SqlHelper()
obj.modify('insert into student(stu_name,class_id) values(%s,%s)', [title, class_id])
obj.close()
return redirect('students')
add_student.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>学生添加</h1>
<form action="{% url 'add_student' %}" method="post">
{% csrf_token %}
<p>学生名称:<input type="text" name="title"></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>
此时访问127.0.0.1:8000/students/如下:
三、学生删除
学生的删除和班级的删除也是差不多的,万变不离其中,只需要获取到学生的唯一id即可删除,我们可以通过get形式获取到id,然后通过数据库删除、跳转会学生列表即可。
- 通过get请求携带着学生的id
- 视图接收到学生id
- 通过学生id进行数据库删除
- 跳转回学生列表
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def del_student(request):
student_id = request.GET.get('student_id')
obj = SqlHelper()
obj.modify('delete from student where id=%s', [student_id, ])
obj.close()
return redirect('students')
此时访问127.0.0.1:8000/students/如下:
可以看到,访问成功后,页面跳转会了学生列表,且视图函数执行了删除的操作。
四、学生编辑
学生编辑和班级的编辑类似,不过学生在点击编辑标签时,我们需要将当前学生的内容展示出来,且是哪个班级的也需要展示,因为如果当我们本来不想编辑,但是却点了提交,班级第一个展示的也不是自己班级,导致班级被修改了。所以,我们需要在班级展示的时候给它选择一个所属班级,那么就要进行id的判断,通过get传学生id无疑是必要的,且还需要使用option标签的selected
属性,表示第一个班级的选中状态。
- 给学生列表的编辑添加get传学生id
- 在get请求时通过学生id获取班级信息
- 在学生列表展示的时候加上判断
- 判断成功后添加option标签的
selected
属性 - post请求提交到视图
- 视图通过传来的学生id进行学生姓名、班级id的数据库更新
- 成功后跳转回学生列表
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def edit_student(request):
obj = SqlHelper()
if request.method == "GET":
class_id = request.GET.get('student_id')
student_class = obj.get_one("SELECT stu.id,stu.`stu_name`,class_id,title FROM student as stu \
INNER JOIN class as cls ON stu.`class_id`=cls.`id` \
where stu.id=%s ", [class_id, ])
class_list = obj.get_list('select id,title from class', [])
context = {
'class_list': class_list,
'student_class': student_class,
}
obj.close()
return render(request, 'edit_student.html', context)
nid = request.GET.get('nid')
title = request.POST.get('title')
class_id = request.POST.get('class_id')
obj.modify('update student set stu_name=%s,class_id=%s where id=%s', [title, class_id, nid, ])
obj.close()
return redirect('students')
edit_student.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>编辑学生</h1>
<form method="post" action="{% url 'edit_student' %}?nid={{ student_class.id }}">
{% csrf_token %}
<p>学生名称:<input type="text" name="title" value="{{ student_class.stu_name }}" /></p>
<p>
所属班级
<select name="class_id">
{% for row in class_list %}
{% if row.id == student_class.class_id %}
<!-- 如果这里班级id等于当前编辑的班级id则替换到当前班级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>
此时访问127.0.0.1:8000/students/如下:
可以看到在编辑页面时,班级是正确的,且提交成功后也进行了数据库的更改及跳转学生列表。
3.老师列表
最后还有一个老师列表,和上述班级、学生列表操作是类似的,不过是获取的时候多了一张表,通过两次的关联就可以获取到相应的值了。因为老师列表的视图及模板都类似,所以这里就先全部定义了,要写视图函数的时候在写上。
一、老师首页
因为之前没有插入老师及与老师关联的班级表数据,所以我们可以先向数据库添加:
insert into teacher(th_name) value('大白')
INSERT INTO teacher(th_name) VALUE('大黑')
insert INto teachers(t_id,c_id) value(9,6)
INSERT INTO teachers(t_id,c_id) VALUE(9,20)
insert INto teachers(t_id,c_id) value(10,7)
这里每个人的班级id、老师id不一样,根据自己班级id及老师id做插入.
urls.py如下:
from django.urls import path
from app01 import views
urlpatterns = [
# 班级列表
path('add_class/', views.add_class, name='add_class'),
path('classes/', views.classes, name='classes'),
path('del_class/', views.del_class, name='del_class'),
path('edit_class/', views.edit_class, name='edit_class'),
# 学生列表
path('students/', views.students, name='students'),
path('add_student/', views.add_student, name='add_student'),
path('del_student/', views.del_student, name='del_student'),
path('edit_student/', views.edit_student, name='edit_student'),
# 老师列表
path('teachers/', views.teachers, name='teachers'),
path('add_teacher/', views.add_teacher, name='add_teacher'),
path('del_teacher/', views.del_teacher, name='del_teacher'),
path('edit_teacher/', views.edit_teacher, name='edit_teacher'),
]
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def teachers(request):
obj = SqlHelper()
# 通过两次关联表获取到老师相关的数据
teacher_list = obj.get_list("SELECT teacher.id AS tid,th_name,class.`id` AS
cid,class.`title` FROM teachers \
INNER JOIN teacher ON teachers.`t_id`=teacher.`id` \
INNER JOIN class ON class.`id`=teachers.`c_id` ", [])
result = {}
for teacher in teacher_list:
tid = teacher['tid']
# 是否已经创建了该列表
if tid in result:
result[tid]['titles'].append(teacher['title'])
result[tid]['cid'].append(teacher['cid'])
else:
result[tid] = {'tid': teacher['tid'], 'th_name': teacher['th_name'], 'cid': [teacher['cid'], ],'titles': [teacher['title'], ]}
obj.close()
print(result.values)
return render(request, 'teachers.html', {'result': result.values()})
def add_teacher(request):
pass
def del_teacher(request):
pass
def edit_teacher(request):
pass
因为老师任教的班级可能有多个,所以我们可以通过id作为key,相同id的值作为value,将相同id的班级id和班级姓名在嵌套一层,班级姓名为titles、班级id为cid,这样所有数据就可以存在一个字典中了,打印result结果:
{9: {'tid': 9, 'th_name': '大白', 'cid': [6, 7], 'titles': ['全栈1班', '全栈4班']}, 10: {'tid': 10, 'th_name': '大黑', 'cid': [7, 16, 20], 'titles': ['全栈4班', '全栈5班', '全栈66班']}}
teachers.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>老师列表</h1>
<a href="{% url 'add_teacher' %}">添加</a>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>班级</th>
<th>教师名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in result %}
<tr>
<td>{{ forloop.counter }}</td>
<td>
{% for class in row.titles %}
<span style="border: 1px solid red">{{ class }}</span>
{% endfor %}
</td>
<td>
{{ row.th_name }}
</td>
<td>
<a href="{% url 'edit_teacher' %}?teacher_id={{ row.tid }}&cid={{ row.cid }}">编辑</a>
<a href="{% url 'del_teacher' %}?teacher_id={{ row.tid }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
此时访问127.0.0.1:8000/teachers/如下:
二、老师添加
老师添加操作和上述班级、学生的添加操作都是类似的,不过就是select标签多了一个多选的选项。
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def add_teacher(request):
obj = SqlHelper()
if request.method == "GET":
class_list = obj.get_list('select * from class ', [])
return render(request, 'add_teacher.html', {'class_list': class_list})
else:
class_list_id = request.POST.getlist('class_list_id')
teacher_name = request.POST.get('title')
teacher_id = obj.create("insert into teacher(th_name) value(%s)", [teacher_name, ])
data_list = [(teacher_id, class_id) for class_id in class_list_id]
obj.multiple_modify("insert into teachers(t_id,c_id) value(%s,%s)", data_list)
return redirect('teachers')
add_teacher.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>添加老师</h1>
<form action="{% url 'add_teacher' %}" method="post">
{% csrf_token %}
<p>老师姓名:<input type="text" name="title"></p>
<p>
任教班级:
<select name="class_list_id" multiple>
{% for row in class_list %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endfor %}
</select>
</p>
<input type="submit" value="提交">
</form>
</body>
</html>
此时访问127.0.0.1:8000/teachers/如下:
可以看到数据已经添加成功并返回给模板了。
三、老师删除
老师删除的操作就更简单了,这里就不详细说明了。
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def del_teacher(request):
obj = SqlHelper()
teacher_id = request.GET.get('teacher_id')
obj.modify('delete from teacher where id=%s', [teacher_id, ])
# 因为数据库设计的时候是级联删除(不写这行也行)
obj.modify('delete from teachers where t_id=%s', [teacher_id, ])
return redirect('teachers')
此时访问127.0.0.1:8000/teachers/如下:
可以看到数据已经删除成功了。
四、老师编辑
最后到了老师编辑,这里涉及到的知识点就有点多了,因为在编辑表的时候,所任教的班级需要显示, 且还可能是任教多个班级,当提交编辑表单的时候还需要判断,还需要在更新到数据库中,如果是少选或者多选都要进行数据库的操作,因此在post请求有两种方法可以提交数据到数据库:
- 方法一、
- 1.在编辑老师的时候获取老师id
- 2.通过老师id删除所有相关联的班级
- 3.通过编辑获取到的老师名字,通过老师id进行数据库更新
- 4.获取到post传来的班级id
(通过getlist获取多个)
- 5.将获取到的班级id依次添加到数据库中
- 方法二、
- 1.在编辑老师的时候获取老师id、对应班级id
- 2.将获取到的班级id用json解析成列表
- 3.新建一个空列表(用于存放需要删除、增加的数据)[
是删除还是添加却决于获取到班级id是否到之前的班级id
] - 4.通过分类完成,将该删除和添加的数据分成两份,最后使用sql语句将其删除、增加。
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
def edit_teacher(request):
obj = SqlHelper()
cid = json.loads(request.GET.get('cid'))
if request.method == "GET":
teacher_id = request.GET.get('teacher_id')
teacher = obj.get_one("select * from teacher where id=%s", [teacher_id, ])
class_list = obj.get_list("select * from class", [])
context = {
'teacher': teacher,
'class_list': class_list,
'cid': cid
}
return render(request, 'edit_teacher.html', context)
else:
class_list_id = request.POST.getlist('class_list_id')
title = request.POST.get('title')
teacher_id = request.GET.get('teacher_id')
obj.modify('update teacher set th_name=%s where id=%s ', [title, teacher_id])
"""第一种方法"""
obj.modify('delete from teachers where t_id=%s', [teacher_id, ])
data_list = [(teacher_id, cls) for cls in class_list_id]
obj.multiple_modify('insert into teachers(t_id,c_id) value (%s,%s)', data_list)
obj.close()
return redirect('teachers')
edit_teacher.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>编辑老师</h1>
<form action="{% url 'edit_teacher' %}?teacher_id={{ teacher.id }}&cid={{ cid }}" method="post">
{% csrf_token %}
<p>
老师姓名:<input type="text" name="title" value="{{ teacher.th_name }}">
</p>
<select name="class_list_id" multiple>
{% for row in class_list %}
{% if row.id in cid %}
<option selected value="{{ row.id }}">{{ row.title }}</option>
{% else %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endif %}
{% endfor %}
</select>
<input type="submit" value="提交">
</form>
</body>
</html>
此时访问127.0.0.1:8000/teachers/如下:
可以看到通过方法一是可以完成编辑操作的。
如果使用方法二,也同样可以实现。
app01/views.py如下:
from django.shortcuts import render, HttpResponse, redirect
from SQL_connection.sqlheper import SqlHelper
import json
def edit_teacher(request):
obj = SqlHelper()
cid = json.loads(request.GET.get('cid'))
if request.method == "GET":
teacher_id = request.GET.get('teacher_id')
teacher = obj.get_one("select * from teacher where id=%s", [teacher_id, ])
class_list = obj.get_list("select * from class", [])
context = {
'teacher': teacher,
'class_list': class_list,
'cid': cid
}
return render(request, 'edit_teacher.html', context)
else:
class_list_id = request.POST.getlist('class_list_id')
title = request.POST.get('title')
teacher_id = request.GET.get('teacher_id')
obj.modify('update teacher set th_name=%s where id=%s ', [title, teacher_id])
"""第二种方法"""
# 如果是在小于的情况下就是添加大于的情况接收删除
cls = []
if len(class_list_id) <= len(cid):
for class_id in class_list_id:
if int(class_id) in cid:
cid.remove(int(class_id))
else:
cls.append((teacher_id, class_id))
obj.multiple_modify('insert into teachers(t_id,c_id) value(%s,%s)', cls)
for row in cid:
obj.modify('delete from teachers where c_id=%s and t_id=%s', [str(row), teacher_id])
obj.close()
else:
for class_id in cid:
if str(class_id) in class_list_id:
class_list_id.remove(str(class_id))
else:
cls.append(class_id)
cls_list = [(teacher_id, str(class_id)) for class_id in cls]
obj.multiple_modify('delete from teachers where t_id=%s and c_id=%s', cls_list)
data_list = [(teacher_id, class_id) for class_id in class_list_id]
obj.multiple_modify('insert into teachers(t_id,c_id) value(%s,%s)', data_list)
obj.close()
return redirect('teachers')
此时访问127.0.0.1:8000/teachers/如下:
此时通过方法二也可以实现。
我们通过这两次方法可以看到,两种的执行效率不一样,方法一的优点在于删除很快,缺点在于增加需要全部重新增加,且如果在删除全部的时候准备增加的时候,报错了那么数据就消失了。
而方法二的优点在于,增加的时候不需要在数据库过多的操作增加很快,且不会重复增加班级、删除也会根据用户选择的班级,进行判断删除,不过缺点也是在于如果用户从多个班级替换到单个班级,那么在删除数据库表的时候就要删除多次。
所以每个方法都各有所长,各有所短,根据实际情况使用。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/66857.html