Django學生信息管理系統 ---- 第5章


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.pyadd_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添加教師信息的頁面效果:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章