文章目录
- 1. 数据库表的结构设计
- 2. 后台引入母板
- 3. 查询班级信息
- 4. 添加班级信息
- 5. 编辑班级信息
- 6. 删除班级信息
- 7. 查询学生信息
- 8. 添加学生信息
- 9. 编辑学生信息
- 10. 删除学生信息
- 11. Bootstrap介绍
- 12. AJAX添加班级信息
- 13. AJAX编辑班级信息
- 14. AJAX删除班级信息
- 15. 数据库操作代码复用
- 16. AJAX添加学生信息
- 17. AJAX编辑学生信息
- 18. AJAX删除学生信息
- 19. 分页展示学生表
- 20. 数据库操作封装
- 21. 添加教师信息
- 22. 查询教师和任课班级信息
- 23. 编辑教师信息
- 24. AJAX删除教师信息
- 25. AJAX添加教师信息
Github:
https://github.com/ThanlonSmith/stu-django
博主极力推荐的Python面试教程,有时间的小伙伴可以看看:
Python 面试100讲(基于Python3.x)
# 创建test数据库
create database test default character set utf8;
# 创建学生表
create table student(id int auto_increment primary key,name varchar(10) not null,class_id int not null);
# 创建班级表
create table class(id int auto_increment primary key, title varchar(20) not null);
# 创建教师表
create table teacher(id int auto_increment primary key,name varchar(10) not null);
# 创建教师班级表
create table teacher2class(id int primary key auto_increment,teacher_id int not null,class_id int not null);
把重复用到的html代码放到一个html文件中,这个html文件被称为母板
,需要用到这些代码的模板可以直接继承这个母板。这个html文件使用的标签是:{% block xxx %} {% endblock %},{% extends '母板.html'%}
。
首先要向班级表中插入一条测试数据:
insert class values(null,'软件工程'),(null,'计算机科学与技术');
可以在项目名所在的目录下创建一个名为 app01
的目录,并在该目录下创建 views.py
文件,下面开始在 urls.py
文件中加入查询班级的路由:
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
# 查询班级信息的路由以及对应的函数(对应views下的classes函数)
path('classes/', views.classes),
]
在 views
下的 classes
函数写查询班级信息的逻辑代码:
# 导入返回模板的函数render和重定向的redirect函数
from django.shortcuts import render, redirect
# 导入pymysql模块用来连接数据库,这里暂时使用pymysql
import pymysql
def classes(request):
'''
查询班级id、班级名称
:param request:对象相关的数据
:return:渲染后的模板
'''
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql语句
cursor.execute("select id,title from class")
# 获取查询到的所有信息
classes_list = cursor.fetchall()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 返回模板和数据
return render(request, 'classes.html', {'classes_list': classes_list})
在 templates
文件夹下新建 classes.html
文件,也就是我们的模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>班级信息</title>
</head>
<body>
<p><a href="/add-class/">添加</a></p>
{% for row in classes_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.title }}</td>
</tr>
<br>
{% endfor %}
</body>
</html>
添加“添加班级信息”的路由,
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('classes/', views.classes),
path('add-class/', views.add_class),
]
在 templates
目录下新建名为 add_class.html
的模板:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加班级信息title>
head>
<body>
<h1>添加班级h1>
<form action="/add-class/" method="post">
<label>班级名称:label>
<input type="text" name="class_title">
<input type="submit" value="提交">
form>
body>
html>
在 views.py
的 add_class
函数中写添加学生班级信息的逻辑代码:
def add_class(request):
# 如果是get请求就返回add_class.html模板就可以
if request.method == 'GET':
return render(request, 'add_class.html')
# 如果是post请求则执行下面的代码
else:
# 获取班级的标题
class_title = request.POST.get('class_title')
# 创建数据库连接对象
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 将班级的名称传到sql语句中
cursor.execute('insert into class(title) values(%s)', class_title)
# cursor.execute("insert into class(title) values(%s)", [class_title, ])
# 提交(查询不需要,其它如添加、修改、更新数据是需要执行commit方法才能将数据插入成功)
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 添加之后就会重定向到/classes/路由,会显示添加后的班级
return redirect('/classes/')
在班级信息页面中点击添加按钮进入添加班级信息界面,添加班级信息后,页面会自动跳转到班级信息页面。
根据客户端传过来的班级id就可编辑班级信息,逻辑代码:
def edit_class(request):
# 如果是get请求,这里额外也需要查询下数据库,把原来的信息也展示出来
if request.method == 'GET':
# 获取客户端传过来的班级id
nid = request.GET.get('nid')
# 创建数据库连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 执行游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql语句
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})
# post请求用来修改班级信息
else:
# nid = request.POST.get('nid') # 放到请求体
nid = request.GET.get('nid') # 放到请求头
title = request.POST.get('title')
# 创建数据库连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql语句
cursor.execute('update class set title=%s where id = %s', [title, nid])
# 提交事务
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
return redirect('/classes/')
需要跳转到编辑信息的模板,将其命名为:edit_class.html
:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改班级信息title>
head>
<body>
<h3>编辑班级信息h3>
<form action="/edit-class/?nid={{ result.id }}" method="post">
<label>班级名称:label>
{# #}
<input type="text" name="title" value="{{ result.title }}">
<input type="submit" value="提交">
form>
body>
html>
浏览器向服务端发送删除数据的请求,服务端接收请求删除数据后向浏览器发送响应,告诉浏览器重定向到 /classes/
。服务端向浏览器发送响应的响应头中有 location:http://127.0.0.1:8000/classes/
,即是:告诉浏览器向此链接发送一次请求。
直接删除就可以了,删除的逻辑是:
def del_class(request):
# 获取客户端传过来的nid,我们要个根据nid来删除数据
nid = request.GET.get('nid')
# 创建连接对象
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql语句
cursor.execute('delete from class where id=%s', nid)
# cursor.execute("insert into class(title) values(%s)", [class_title, ])
# 提交事务
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
return redirect('/classes/')
首先向学生表中插入测试数据:
insert into student values(null,'thanlon',1);
insert into student values(null,'kiku',2);
查询学生信息的逻辑代码:
def students(request):
'''
学生列表
:param request:封装了请求相关的所有信息
:return:返回模板和数据
'''
# 创建连接对象
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql语句
cursor.execute(
'select student.id,student.name,class.title from student left join class on student.class_id=class.id')
# 获取查询到的所有数据
student_list = cursor.fetchall()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 返回模板和数据
return render(request, 'students.html', {'student_list': student_list})
新建显示学生信息的模板 students.html
:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>学生信息title>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
head>
<body>
<div class="container" style="margin-top: 20px">
<div class="row">
<div class="col-md-4">
<a class="btn btn-default" href="">添加a>p>
<table class="table table-hover text-center">
<tr>
<th class="text-center">IDth>
<th class="text-center">学生姓名th>
<th class="text-center">学生班级th>
<th class="text-center">操作th>
tr>
{% for row in student_list %}
<tr>
<td>{{ row.id }}td>
<td>{{ row.name }}td>
<td>{{ row.title }}td>
<td><a href="/">编辑a> <a href="">删除a>
td>
tr>
{% endfor %}
table>
div>
div>
div>
body>
html>
和添加班级信息同样的逻辑:
def add_student(request):
# 如果是get请求
if request.method == 'GET':
# 创建连接对象
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行查询的sql语句
cursor.execute("select id,title from class")
# 获取查询到的所有数据
classe_list = cursor.fetchall()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 返回模板和数据
return render(request, 'add_student.html', {'class_list': classe_list})
# 如果是post请求
else:
# 获取学生的名字
name = request.POST.get('name')
# 获取学生的班级id
class_id = request.POST.get('class_id')
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 将学生的名字和班级的id信息放到sql中
cursor.execute("insert into student(name,class_id) values (%s,%s)", [name, class_id, ])
# 执行事务
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 返回模板
return redirect('/students/')
下面这部分是模板 add_student.html
,注意模板语法的书写:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加学生信息title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
head>
<body>
<div class="container" style="margin-top: 20px">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<form action="/add-student/" method="post"> {#如果没有写,默热提交到当前url#}
<div class="form-group">
<label>姓名:label>
<input type="text" class="form-control" id="" placeholder="" name="name">
div>
<div class="form-group">
<select class="form-control" name="class_id">
{% for row in class_list %}
<option value="{{ row.id }}">{{ row.title }}option>
{% endfor %}
select>
div>
<button type="submit" class="btn btn-primary">添加button>
form>
div>
div>
div>
body>
html>
首先写将班级信息和当前学生信息渲染到编辑学生信息模板的逻辑,然后才是编辑学生信息的逻辑:
def edit_student(request):
"""
编辑学生信息
"""
# get请求时
if request.method == 'GET':
# 获取传过来的学生id
nid = request.GET.get('nid')
# 创建连接对象
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行查询班级信息的sql
cursor.execute("select id,title from class")
# 获取所有班级信息
class_list = cursor.fetchall()
# 执行查询当前学生编号、名字和班级id的sql
cursor.execute("select id,name,class_id from student where id=%s", nid)
# 获取查询到的数据。因为数据只有一条,所以这里使用fetchone()就可以了
current_student_info = cursor.fetchone()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 返回模板和数据
return render(request, 'edit_student.html',
{'class_list': class_list, 'current_student_info': current_student_info})
# post请求时
else:
# 从url中获取学生的id
nid = request.GET.get('nid')
# 从请求体(form表单)中获取当前学生的姓名
name = request.POST.get('name')
# 从请求体中获取当前学生的班级id
class_id = request.POST.get('class_id')
# 创建练级
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql语句
cursor.execute("update student set name=%s,class_id=%s where id = %s", [name, class_id, nid])
# 提交事务
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 重定向到学生信息页面
return redirect('/students/')
编辑学生信息的模板 edit_student.html
:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加学生信息title>
head>
<body>
<div class="container" style="margin-top: 20px">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<form action="/edit-student/?nid={{ current_student_info.id }}" method="post">
{# 还可以设置input标签将其隐藏#}
<div class="form-group">
<label>姓名:label>
<input type="text" class="form-control" id="" placeholder="" name="name"
value="{{ current_student_info.name }}">
div>
<div class="form-group">
<select class="form-control" name="class_id">
{% for row in class_list %}
{% if row.id == current_student_info.class_id %}
<option selected="selected" value="{{ row.id }}">{{ row.title }}option>
{% else %}
<option value="{{ row.id }}">{{ row.title }}option>
{% endif %}
{% endfor %}
select>
div>
<button type="submit" class="btn btn-primary">更新button>
form>
div>
div>
div>
body>
html>
删除学生信息的逻辑,与删除班级相同,也是比较简单的:
def del_student(request):
'''
删除学生信息
'''
# 获取学生编号
nid = request.GET.get('nid')
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql
cursor.execute('delete from student where id=%s', nid)
# 提交事务
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 返回模板
return redirect('/students/')
Bootstrap是一个包含css和js的代码库
,有很多已经构建好的组件,模态对话框就是其中的一种,因为接下来要使用到模态对话框,我们直接用就可以这个组件就可以。Bootstrap还支持响应式布局
,响应式都是基于css的media来实现的,下面是一个使用media实现响应式的例子:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<style>
.page-header {
height: 20px;
background: rebeccapurple;
}
@media (max-width: 1200px) {
.page-header {
height: 20px;
background: yellowgreen;
}
}
@media (max-width: 1000px) {
.page-header {
height: 20px;
background: lightcoral;
}
}
@media (max-width: 300px) {
.page-header {
height: 20px;
background: saddlebrown;
}
}
style>
<body>
<div class="page-header">div>
body>
html>
当页面宽度大于等于是1200px的时候,显示yellowgreen的颜色,当页面宽度大于等于是1000px的时候,显示lightcoral的颜色,当页面宽度大于等于300px的时候,显示saddlebrown的颜色。
添加班级信息的逻辑:
def add_class_modal(request):
# 获取班级名称
title = request.POST.get('title')
# 输入的班级名称的长度需要大于0
if len(title) > 0:
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql
cursor.execute('insert into class (title) values (%s)', title)
# 提交事务
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 向前台返回ok
return HttpResponse('ok')
else:
# 如果提交过来的班级名称长度是小于0的,向前台返回不能为空,给前台提示信息
return HttpResponse('班级不能为空!')
添加一个模态对话框用来添加班级信息,由于以Form表单的方式提交,不论班级信息填写正确还是错误都会提交到后台并刷新页面
,这样模态框就会消失。所以,我们这里使用AJAX的方式来提交请求,AJAX可以在不刷新页面的情况下与后台交互
:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>班级信息title>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<style>
.hide {display: none;}
.shadow {position: fixed; top: 0; bottom: 0; left: 0; right: 0; background-color: black; opacity: 0.4; z-index: 999; }
.modal_layer { position: fixed; z-index: 1000; left: 50%; top: 50%; background-color: white; width: 400px; height: 150px; margin-top: -150px; margin-left: -200px;}
style>
head>
<body>
<div class="container" style="margin-top: 20px">
<div class="row">
<div class="col-md-4 col-md-offset-4">
{# <a class="btn btn-default" href="/add-class/">添加a>#}
<a class="btn btn-default" id="addClasses">添加班级信息a>
<div class="shadow hide" id="shadow">div>
<div class="modal_layer hide" id="modal_layer">
<div class="panel panel-primary">
<div class="panel-heading">添加班级信息div>
<div class="panel-body">
<form action="/add-class-modal/" method="post">
<div class="form-group">
<label for="">班级名称label>
<input type="text" name="title" class="form-control" id="title" placeholder=""
autofocus>
<span id="error" style="color: red">span>
div>
<input type="button" class="btn btn-primary" value="确认添加" id="add_class">
form>
div>
div>
div>
<table class="table table-hover text-center">
<tr>
<th class="text-center">班级IDth>
<th class="text-center">班级名称th>
<th class="text-center">操作th>
tr>
{% for row in classes_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 %}
table>
div>
div>
div>
body>
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous">script>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous">
script>
<script>
$(document).ready(function () {
$('#addClasses').click(function () {
$('#shadow').removeClass('hide');
$('#modal_layer').removeClass('hide');
});
$('#add_class').click(function () {
$.ajax({
url: '/add-class-modal/',
type: 'POST',
data: {'title': $('#title').val()},
success: function (data) {
//当服务端处理完,返回数据时,自动调用该函数
if (data == 'ok') {
alert('添加成功!');
location.href = '/classes/';
} else {
$('#error').text(data);
}
}
})
});
$('#shadow').click(function () {
$('#shadow').addClass('hide');
$('#modal_layer').addClass('hide');
});
})
script>
html>
模块对话框适用于 少量的输入标签和数据
的情况下,url适用于 操作多、对于大量的数据
的操作。
还是使用之前编辑班级信息的逻辑代码,可以在原来的基础上可以加上一些表单字段的判断:
def edit_class(request):
'''
编辑班级信息
'''
# 获取班级编号
class_id = request.GET.get('class_id')
# 获取班级名称
class_title = request.GET.get('class_title')
# 获取的名称长度要大于0
if len(class_title) > 0:
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql
cursor.execute('update class set title=%s where id = %s', [class_title, class_id])
# 提交事务
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 向前台返回的data,前台通过这里来判断编辑是否完成
return HttpResponse('ok')
else:
# 返回错误提示信息
return HttpResponse('班级不能为空!')
使用AJAX发送请求和获取服务端传过来的数据:
<script>
$(document).ready(function () {
function edit_class_modal(ths) {
$('#shadow').removeClass('hide');
$('#modal_edit').removeClass('hide');
var row = $(ths).parent().prevAll();
{#console.log(v[0])#}
console.log($(row[0]).text());
content_title = $(row[0]).text();
content_id = $(row[1]).text();
$('#edit_title').val(content_title);
$('#edit_id').val(content_id);
}
$('#edit_class').click(function () {
$.ajax({
url: '/edit-class/',
type: 'GET',
data: {
'class_id': $('#edit_id').val(),
'class_title': $('#edit_title').val()
},
success: function (data) {
if (data == 'ok') {
location.href = '/classes/'
} else {
$('#edit_error').text(data);
}
}
})
})
$('#close_edit_modal').click(function () {
$('#shadow').addClass('hide');
$('#modal_edit').addClass('hide');
});
});
script>
删除班级的逻辑:
def del_class(request):
'''
删除班级信息
'''
# 获取班级编号,需要通过编号删除班级信息
class_id = request.GET.get('class_id')
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 将班级id传到sql豫剧中并执行sql
cursor.execute('delete from class where id=%s', class_id)
# 提交事务
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 返回操作成功的标识
return HttpResponse('ok')
AJAX删除班级信息:
<script>
function del_class(ths) {
var row = $(ths).parent().prevAll();
class_id = $(row[1]).text();
$.ajax({
url: '/del-class/',
type: 'get',
data: {'class_id': class_id},
success: function (data) {
if (data == 'ok') {
location.href = '/classes/'
} else {
alert('删除失败!')
}
}
})
}
script>
视图函数操作数据库时有很多重复的操作步骤,可以把这些操作放到一个函数中,
sqlhelper.py
:
import pymysql
def get_list(sql, args):
"""
返回查询到的所有结果
:param sql:
:param args:
:return:
"""
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test', charset='utf8')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql
cursor.execute(sql, args)
# 获取查询到的内容
ret = cursor.fetchall()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
return ret
def get_one(sql, args):
"""
返回查询到的一条结果
:param sql:
:param args:
:return:
"""
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test', charset='utf8')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql
cursor.execute(sql, args)
# 获取查询到的内容
ret = cursor.fetchone()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
return ret
def modify(sql, args):
"""
修改和删除操作
:param sql:
:param args:
:return:
"""
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test', charset='utf8')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行sql
cursor.execute(sql, args)
# 提交事务
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
添加学生信息的业务逻辑:
def add_student_modal(request):
"""
模态对话框的方式添加班级信息
:param request:
:return:
"""
ret = {'status': True, 'msg': None}
try:
name = request.POST.get('name')
class_id = request.POST.get('class_id')
if len(name) <= 0 or len(class_id) <= 0:
ret['status'] = False
ret['msg'] = '学生姓名或班级不能为空'
return HttpResponse(json.dumps(ret))
sqlhelper.modify(sql='insert into student(name,class_id) values(%s,%s)', args=[name, class_id])
except Exception as e:
ret['status'] = False
ret['msg'] = str(e)
return HttpResponse(json.dumps(ret))
AJAX添加学生信息:
$('#add_student').click(function () {
$.ajax({
url: '/user/add_student_modal/',
type: 'POST',
data: {
'name': $('#name').val(),
'class_id': $('#class_id').val()
},
success: function (data) {
data = JSON.parse(data) //把后台传过来的字符串转换成js中的对象
if (data.status) {
location.href = '/user/student/'
} else {
$('#add_student_error').text(data.msg);
}
}
});
})
编辑学生信息的业务逻辑:
def edit_student_modal(request):
"""
模态框编辑学生信息
:param request:
:return:
"""
ret = {'status': True, 'msg': None}
try:
student_id = request.POST.get('student_id')
class_id = request.POST.get('class_id_edit')
student_name = request.POST.get('student_name')
sqlhelper.modify('update student set name=%s,class_id=%s where id=%s',
[student_name, class_id, student_id])
except Exception as e:
ret['status'] = False
ret['msg'] = str(e)
return HttpResponse(json.dumps(ret))
AJAX编辑学生信息:
function edit_student(ths) {
//编辑学生信息前的操作
$('#shadow').removeClass('hide');
$('#modal_edit_student').removeClass('hide');
var row = $(ths).parent().prevAll();
//学生ID
student_id = $(row[2]).text();
//学生姓名
student_name = $(row[1]).text();
//班级id
class_id_edit = $(row[0]).attr('cls_id');
$('#student_name').val(student_name);
//id不能重复,如果重复,哪个在前找哪个
$('#class_id_edit').val(class_id_edit);
$('#student_id').val(student_id);
}
//修改班级信息
$('#edit_student').click(function () {
$.ajax({
url: '/user/edit_student_modal/',
type: 'POST',
data: {
'student_id': $('#student_id').val(),
'student_name': $('#student_name').val(),
'class_id_edit': $('#class_id_edit').val(),
},
success: function (data) {
data = JSON.parse(data);
if (data.status) {
location.reload()
} else {
$('#edit_error').text(data.msg);
}
}
})
})
删除学生信息的业务逻辑:
def del_student_modal(request):
"""
模态框删除学生信息
:param request:
:return:
"""
ret = {'status': True, 'msg': None}
try:
student_id = request.GET.get('student_id')
sqlhelper.modify('delete from student where id=%s', [student_id, ])
except Exception as e:
ret['status'] = False
ret['msg'] = str(e)
return HttpResponse(json.dumps(ret))
AJAX删除学生信息:
function del_student(ths) {
var row = $(ths).parent().prevAll();
student_id = $(row[2]).text();
$.ajax({
url: '/user/del_student_modal/',
type: 'GET',
data: {
'student_id': student_id
},
success: function (data) {
data = JSON.parse(data);
if (data.status) {
location.reload()
} else {
alert('删除失败!');
}
}
})
}
分页后台逻辑:
def student(request):
'''
学生信息列表
:param request:封装了请求相关的所有信息
:return:返回模板和数据
'''
# 创建连接对象
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# 创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 查询学生信息列表
cursor.execute(
'select student.id,student.name,class_id,class.title from student left join class on student.class_id=class.id')
# 获取查询到的所有数据
student_list = cursor.fetchall()
paginator = Paginator(student_list, 1)
current_page = request.GET.get('page')
try:
posts = paginator.page(current_page)
except PageNotAnInteger as e:
posts = paginator.page(1)
except EmptyPage as e:
posts = paginator.page(1)
# 查询班级信息
cursor.execute('select id,title from class')
# 获取查询到的所有班级列表
class_list = cursor.fetchall()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 返回模板和数据
return render(request, 'student.html', {'student_list': student_list, 'class_list': class_list, 'posts': posts})
前台分页展示:
<table class="table table-hover text-center" style="background: white;margin-bottom: 0">
<tr>
<th class="text-center">IDth>
<th class="text-center">学生姓名th>
<th class="text-center">学生班级th>
<th class="text-center">操作th>
tr>
{% for row in posts.object_list %}
<tr>
<td>{{ row.id }}td>
<td>{{ row.name }}td>
<td cls_id="{{ row.class_id }}">{{ row.title }}td>
{#<td>{{ row.class_id }}td>#}
<td>
<a href="/user/edit_student/?nid={{ row.id }}">编辑(1)a>
<a href="javascript:;" onclick="edit_student(this)">编辑(2)a>
<a href="/user/del_student/?nid={{ row.id }}">删除(1)a>
<a href="javascript:;" onclick="del_student(this)">删除(2)a>
td>
tr>
{% endfor %}
table>
<nav aria-label="Page navigation" class="text-left">
<ul class="pagination">
{% if posts.has_previous %}
<li>
{#<a href="/user/student?page={{ posts.previous_page_number }}">上一页a>#}
<a href="{% url 'student' %}?page={{ posts.previous_page_number }}">上一页a>
li>
{% endif %}
{% if posts.has_next %}
<li>
{#<a href="/user/student?page={{ posts.next_page_number }}">下一页a>#}
<a href="{% url 'student' %}?page={{ posts.next_page_number }}">下一页a>
li>
{% endif %}
ul>
nav>
将数据库操作封装在类中,减少了重复的代码,使代码的非常友好的可读性和可维护性的同时,还提高了系统的执行效率:
import pymysql
class SqlHelper:
def __init__(self):
self.conn()
def conn(self):
self.conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test',
charset='utf8')
self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)
def get_list(self, sql, args):
self.cursor.execute(sql, args)
result = self.cursor.fetchall()
return result
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()
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()
后台添加教师信息的业务逻辑:
def add_teacher(request):
"""
添加教师
:param request:
:return:
"""
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')
obj = sqlhelper.SqlHelper()
teacher_id = obj.create('insert into teacher(name) values (%s)', [name, ])
class_ids = request.POST.getlist('class_ids') # ['1', '8', '9', '10']
# 多次连接,多次提交
"""
for class_id in class_ids:
sqlhelper.modify('insert into teacher2class(teacher_id,class_id) values (%s,%s)', [teacher_id, class_id])
"""
# 一次连接,多次提交
"""
for class_id in class_ids:
obj.modify('insert into teacher2class(teacher_id,class_id) values (%s,%s)', [teacher_id, class_id])
obj.close()
"""
# 一次连接,一次提交
data_list = [] # [(9, '8'), (9, '9'), (9, '10')]
for class_id in class_ids:
data_list.append((teacher_id, class_id))
obj.multiple_modify('insert into teacher2class(teacher_id,class_id) values (%s,%s)', data_list)
obj.close()
return render(request, 'teacher.html')
前台添加教师信息:
...
<form action="/user/add_teacher/" method="post">
<div class="form-group">
<label>教师姓名:label>
<input type="text" class="form-control" id="" placeholder="请输入教师的姓名" name="name">
div>
<div class="form-group">
<select multiple class="form-control" name="class_ids">
{% for row in class_list %}
<option value="{{ row.id }}">{{ row.title }}option>
{% endfor %}
select>
div>
<button type="submit" class="btn btn-primary">添加button>
form>
...
查询教师和任课班级信息的业务逻辑:
def teacher(request):
"""
查询教师和任课班级信息
:param request:
:return:
"""
obj = sqlhelper.SqlHelper()
teacher_list = obj.get_list(
'select teacher.id as tid,teacher.name,class.title from teacher left join teacher2class on teacher.id = teacher2class.teacher_id left join class on teacher2class.class_id = class.id ;',
[])
"""
print(teacher_list)
[
{'tid': 1, 'name': '李娇', 'title': '网络工程'},
{'tid': 1, 'name': '李娇', 'title': '计算机科学与技术'},
{'tid': 1, 'name': '李娇', 'title': '软件技术'},
{'tid': 1, 'name': '李娇', 'title': '软件工程'},
{'tid': 2, 'name': '李晓', 'title': '网络工程'},
{'tid': 2, 'name': '李晓', 'title': '软件工程'}
]
"""
result = {}
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(ret)
{
1: {'tid': 1, 'name': '李娇', 'titles': ['网络工程', '计算机科学与技术', '软件技术', '软件工程']},
2: {'tid': 2, 'name': '李晓', 'titles': ['网络工程', '软件工程']}
}
"""
return render(request, 'teacher.html', {'teacher_list': result.values()})
前台查询教师和任课班级信息:
...
<table class="table table-hover text-center" style="background: white;margin-bottom: 0">
<tr>
<th class="text-center">IDth>
<th class="text-center">教师姓名th>
<th class="text-center">任教班级th>
<th class="text-center">操作th>
tr>
{% for row in teacher_list %}
<tr>
<td>{{ row.tid }}td>
<td>{{ row.name }}td>
<td>
{% for item in row.titles %}
<span>{{ item }}span>
{% endfor %}
td>
<td>
<a href="/user/edit_teacher/?nid={{ row.tid }}">编辑a>
<a href="/user/del_teacher/?nid={{ row.tid }}">删除a>
td>
tr>
{% endfor %}
table>
...
后台编辑教师信息逻辑:
def edit_teacher(request):
if request.method == 'GET':
nid = request.GET.get('nid')
obj = sqlhelper.SqlHelper()
# 当前教师的信息
teacher_info = obj.get_one('select id,name from teacher where id = %s', [nid, ])
# 当前教师的任教班级的id信息
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', [])
"""
print(teacher_list) # {'id': 2, 'name': '李晓'}
print(class_list) # [{'id': 1, 'title': '软件工程'}, {'id': 8, 'title': '软件技术'}, {'id': 9, 'title': '计算机科学与技术'}, {'id': 10, 'title': '网络工程'}]
print(class_id_list) # [{'class_id': 1}, {'class_id': 10}]
"""
obj.close()
temp = []
for item in class_id_list:
temp.append(item['class_id'])
"""
print(temp) # [1, 10]
"""
return render(request, 'edit_teacher.html',
{'class_list': class_list, 'teacher_info': teacher_info, 'class_id_list': temp})
else:
# 获取post请求的url上的参数
nid = request.GET.get('nid')
print(nid)
name = request.POST.get('name')
class_ids = request.POST.getlist('class_ids') # ['1', '8', '9', '10']
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 = [] # [('1', '1'), ('1', '8'), ('1', '9'), ('1', '10')]
"""
for class_id in class_ids:
temp = (nid, class_id,)
data_list.append(temp)
"""
# 使用lambda表达式
func = lambda nid, class_id: data_list.append((nid, class_id))
for class_id in class_ids:
func(nid, class_id)
obj.multiple_modify('insert into teacher2class(teacher_id,class_id) values (%s,%s)', data_list)
return redirect('/user/teacher/')
前台编辑教师信息:
...
<form action="/user/edit_teacher/?nid={{ teacher_info.id }}" method="post">
<div class="form-group">
<label>教师姓名:label>
<input type="text" class="form-control" id="" placeholder="" name="name"
value="{{ teacher_info.name }}">
div>
<div class="form-group">
<select multiple class="form-control" name="class_ids">
{% for item in class_list %}
{% if item.id in class_id_list %}
<option selected value="{{ item.id }}">{{ item.title }}option>
{% else %}
<option value="{{ item.id }}">{{ item.title }}option>
{% endif %}
{% endfor %}
select>
div>
<button type="submit" class="btn btn-primary">更新button>
form>
...
AJAX方式删除教师信息的后台逻辑:
def del_teacher_modal(request):
"""
AJAX的方式删除教师信息
:param request:
:return:
"""
if request.method == 'GET':
ret = {'status': True, 'msg': None}
try:
obj = sqlhelper.SqlHelper()
tid = request.GET.get('teacher_id')
obj.modify('delete from teacher where id =%s', [tid])
obj.modify('delete from teacher2class where teacher_id = %s', [tid])
obj.close()
except Exception as e:
ret['status'] = False
ret['msg'] = "删除失败!"
return HttpResponse(json.dumps(ret))
前台的部分代码:
{% for row in teacher_list %}
<tr>
<td>{{ row.tid }}td>
<td>{{ row.name }}td>
<td>
{% for item in row.titles %}
<span>{{ item }}span>
{% endfor %}
td>
<td>
<a href="/user/edit_teacher/?nid={{ row.tid }}">编辑a>
<a href="javascript:;" class="del_teacher" onclick="del_teacher_modal(this)">删除a>
td>
tr>
{% endfor %}
...
<script>
...
//Ajax删除教师信息
function del_teacher_modal(ths) {
falg = confirm('确定要删除?')
if (falg) {
var row = $(ths).parent().prevAll();
teacher_id = $(row[2]).text();
$.ajax({
url: '/user/del_teacher_modal/',
type: 'get',
data: {'teacher_id': teacher_id},
dataType: 'json',
success: function (arg) {
if (arg.status) {
location.reload()
} else {
alert(arg.msg)
}
}
})
}
}
...
script>
AJAX添加教师信息后台逻辑:
def add_teacher_modal(request):
"""
AJAX的方式添加教师信息
:param request:
:return:
"""
if request.method == 'GET':
obj = sqlhelper.SqlHelper()
class_list = obj.get_list('select id,title from class', [])
import time
# 这里是用来模拟用户网站压力比较大的情况下
time.sleep(0.2)
obj.close()
return HttpResponse(json.dumps(class_list))
if request.method == 'POST':
ret = {'status': True, 'msg': None}
# 一般ajax请求要加上try
try:
name = request.POST.get('name')
class_ids = request.POST.getlist('class_ids') # ['1', '8', '9', '10']
# print(name,class_ids) #奈何 ['9', '10']
obj = sqlhelper.SqlHelper()
teacher_id = obj.create('insert into teacher(name) values (%s) ', [name, ])
data_list = []
func = lambda item: data_list.append((teacher_id, item))
for item in class_ids:
func(item)
# print(data_list) # [(8, '8'), (8, '10')]
obj.multiple_modify('insert teacher2class(teacher_id,class_id) values(%s,%s)', data_list)
obj.close()
except Exception as e:
ret['status'] = False
ret['msg'] = '处理失败!'
return HttpResponse(json.dumps(ret))
前台AJAX添加教师信息:
<script>
$(function () {
addBtn();
shadow_btn();
close_btn();
add_teacher_modal();
})
function shadow_btn() {
$('#shadow').click(function () {
$('#shadow,#modal_add_teacher').addClass('hide');
});
}
function close_btn() {
$('#close_btn').click(function () {
$('#shadow,#modal_add_teacher').addClass('hide');
});
}
//点击按钮之后如果数据没有拿到就不断动画加载
function addBtn() {
$('#addBtn').click(function () {
$('#shadow').removeClass('hide');
$('#loading').removeClass('hide');
$.ajax({
url: '/user/add_teacher_modal/',
type: 'get',
dataType: 'json',//拿到的是对象
success: function (arg) {
//alert(arg)//[object Object],[object Object],[object Object],[object Object]
$('#class_ids').html('') //保证上一次的标签内容不会留存再页面上
$.each(arg, function (i, row) {
var tag = $("").html(row.title);
tag.attr('value', row.id)
$('#class_ids').append(tag)
})
$('#loading').addClass('hide');
$('#modal_add_teacher').removeClass('hide');
}
})
})
}
//Ajax添加教师信息
function add_teacher_modal() {
$('#addTeacherBtn').click(function () {
var name = $('#name').val();
var class_ids = $('#class_ids').val();//['9', '10']
$.ajax({
url: '/user/add_teacher_modal/',
type: 'POST',
data: {'name': name, 'class_ids': class_ids},
traditional: true,//如果提交的数据有列表,需要添加这个属性
dataType: 'json', //如果后台返回的是json格式的数据则这里必须写上json,大小写忽略
success: function (arg) {
if (arg.status) {
location.reload();
} else {
$('#add_teacher_error').text(arg.msg);
}
}
})
})
}
script>