文章目錄
Github:
https://github.com/ThanlonSmith/stu-django
博主極力推薦的Python面試教程,有時間的小夥伴可以看看:
Python 面試100講(基於Python3.x)
1. 數據庫表的結構設計
# 創建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);
2. 後臺引入母板
把重複用到的html代碼放到一個html文件中,這個html文件被稱爲母板
,需要用到這些代碼的模板可以直接繼承這個母板。這個html文件使用的標籤是:{% block xxx %} {% endblock %},{% extends '母板.html'%}
。
3. 查詢班級信息
首先要向班級表中插入一條測試數據:
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>
查詢班級信息頁面:
4. 添加班級信息
添加“添加班級信息”的路由,
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
的模板:
<!DOCTYPE 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/')
在班級信息頁面中點擊添加按鈕進入添加班級信息界面,添加班級信息後,頁面會自動跳轉到班級信息頁面。
添加班級信息頁面效果:
5. 編輯班級信息
根據客戶端傳過來的班級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
:
<!DOCTYPE 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"style="display: none" value="{{ result.id }}">#}
<input type="text" name="title" value="{{ result.title }}">
<input type="submit" value="提交">
</form>
</body>
</html>
編輯班級信息頁面:
6. 刪除班級信息
瀏覽器向服務端發送刪除數據的請求,服務端接收請求刪除數據後向瀏覽器發送響應,告訴瀏覽器重定向到 /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/')
7. 查詢學生信息
首先向學生表中插入測試數據:
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
:
<!DOCTYPE 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">ID</th>
<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>
查詢學生信息頁面:
8. 添加學生信息
和添加班級信息同樣的邏輯:
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
,注意模板語法的書寫:
<!DOCTYPE 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>
添加學生信息頁面:
9. 編輯學生信息
首先寫將班級信息和當前學生信息渲染到編輯學生信息模板的邏輯,然後纔是編輯學生信息的邏輯:
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
:
<!DOCTYPE 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>
編輯學生信息頁面:
10. 刪除學生信息
刪除學生信息的邏輯,與刪除班級相同,也是比較簡單的:
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/')
11. Bootstrap介紹
Bootstrap是一個包含css和js的代碼庫
,有很多已經構建好的組件,模態對話框就是其中的一種,因爲接下來要使用到模態對話框,我們直接用就可以這個組件就可以。Bootstrap還支持響應式佈局
,響應式都是基於css的media來實現的,下面是一個使用media實現響應式的例子:
<!doctype html>
<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>Document</title>
</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的顏色。
12. AJAX添加班級信息
添加班級信息的邏輯:
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可以在不刷新頁面的情況下與後臺交互
:
<!DOCTYPE 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">
<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">班級ID</th>
<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適用於 操作多、對於大量的數據
的操作。
AJAX添加班級信息頁面:
13. AJAX編輯班級信息
還是使用之前編輯班級信息的邏輯代碼,可以在原來的基礎上可以加上一些表單字段的判斷:
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>
AJAX編輯班級信息頁面:
14. AJAX刪除班級信息
刪除班級的邏輯:
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>
15. 數據庫操作代碼複用
視圖函數操作數據庫時有很多重複的操作步驟,可以把這些操作放到一個函數中,
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()
16. AJAX添加學生信息
添加學生信息的業務邏輯:
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);
}
}
});
})
AJAX添加學生信息:
17. AJAX編輯學生信息
編輯學生信息的業務邏輯:
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);
}
}
})
})
AJAX編輯學生信息頁面:
18. AJAX刪除學生信息
刪除學生信息的業務邏輯:
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('刪除失敗!');
}
}
})
}
19. 分頁展示學生表
分頁後臺邏輯:
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">ID</th>
<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>
<!--/學生信息展示-->
分頁展示效果圖:
20. 數據庫操作封裝
將數據庫操作封裝在類中,減少了重複的代碼,使代碼的非常友好的可讀性和可維護性的同時,還提高了系統的執行效率:
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()
21. 添加教師信息
後臺添加教師信息的業務邏輯:
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>
...
添加教師信息頁面效果:
22. 查詢教師和任課班級信息
查詢教師和任課班級信息的業務邏輯:
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">ID</th>
<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>
...
前臺查詢教師和任課班級信息的頁面效果:
23. 編輯教師信息
後臺編輯教師信息邏輯:
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>
...
前臺編輯教師信息的頁面效果:
24. AJAX刪除教師信息
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>
前臺的效果圖:
25. AJAX添加教師信息
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 = $("<option></option>").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>
前臺AJAX添加教師信息的頁面效果: