學員管理系統(簡單的Django設計)

學員管理系統(簡單的Django設計)

學員管理系統

項目規劃階段

項目背景

近年來老男孩教育的入學學員數量穩步快速增加,傳統的excel統計管理學員信息的方式已經沒法知足日漸增加的業務需求。所以公司急需一套方便易用的「學員管理系統」,來提升公司在校學員信息的收集和處理能力。鑑於Python學院全棧x期的學員都聰明伶俐可愛至極,所以公司領導通過慎重考慮特決定將此項目交給你們來開發。html

項目需求

本次學員管理系統設計開發,時間緊任務重,但願各位開發人員戒驕戒躁戒菸戒酒,儘快完成項目的開發。前端

具體需求爲:mysql

學員管理系統有三個角色:學生、老師和班級。sql

學生有姓名和所屬班級。數據庫

班級信息有:班級名稱。後端

老師信息有:姓名瀏覽器

老師能夠帶多個班級,每一個班級不一樣階段也會有不一樣的老師講課。數據結構

項目週期

越快越好app

項目開發階段

表結構設計

  View Code

前端部分

 使用Bootstrap搭建的管理後臺頁面模塊化

班級信息管理功能開發

視圖函數:

咱們把全部的處理請求相關的函數從 urls.py中拿出來,統一放在一個叫views.py的文件中,這樣就把代碼模塊化,實現不一樣功能的代碼放在不一樣的模塊。

urls.py文件中只放置 URL和函數的對應關係

views.py 文件中只放置那些針對不一樣URL執行的函數

注意:

這個時候就須要在urls.py中導入views.py文件(views前面加.代表從當前目錄下導入)

from .views import index, login, class_list, delete_class, add_class, edit_class

展現全部的班級列表

後端部分

複製代碼
# 展現全部的班級列表
def class_list(request):
    # 這個函數是展現全部的班級列表
    # 1. 去數據庫裏取數據
    # 鏈接數據庫
    conn = pymysql.connect(host="localhost", user="root", password="root1234", database="s8", charset="utf8")
    # 指定pymysql查詢出的每條數據的類型是字典類型({"字段名": "值"}) *****
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 寫好查詢的SQL語句
    sql = "select id, cname from class order by id;"
    # 執行上面定義好的SQL語句
    cursor.execute(sql)
    # 拿到全部查詢到的結果
    # 此處查詢結果是一個大列表,裏面是一個一個字典
    ret = cursor.fetchall()
    # 關閉鏈接
    cursor.close()
    conn.close()
    # 2. 用數據去替換HTML頁面中的特殊符號,特殊符號是按照Django模板語言的語法寫好的
    # render()的第三個參數是一個字典,字典的key是什麼,HTML文件中的變量名就寫什麼
    return render(request, "class_list.html", {"class_list": ret})
複製代碼

頁面部分

這裏用到了Django模板語言的for循環,模板語言部份內容詳見頁面下方的超連接

複製代碼
<!-- Table -->
<div class="my-table-wrapper">
  <table class="table table-bordered table-striped">
    <thead>
    <tr>
      <th>#</th>
      <th>班級ID</th>
      <th>班級名稱</th>
      <th>操做</th>
    </tr>
    </thead>
    <tbody>
    {% for class in class_list %}
          <tr>
          <td>{{ forloop.counter }}</td>
          <td scope="row">{{ class.id }}</td>
          <td>{{ class.cname }}</td>
          <td class="text-center">
              <a href="/edit_class/?class_id={{ class.id }}" type="button" class="btn btn-sm btn-info" aria-label="Left Align">
              <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>新頁面編輯
            </a>
            <a type="button" class="btn btn-sm btn-success" aria-label="Left Align">
              <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>編輯
            </a>
          <a href="/delete_class/?class_id={{ class.id }}" type="button" class="btn btn-sm btn-danger" aria-label="Left Align">
            <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>刪除
          </a>
          </td>
        </tr>
    {% endfor %}
    </tbody>
  </table>
複製代碼

刪除班級

後端部分

點擊班級列表 表格中 對應班級後面的 刪除按鈕(a標籤),向後端發送get請求,而且攜帶當前班級的ID。

後端拿到 要刪除的班級的ID值,去數據庫中執行刪除操做

複製代碼
# 刪除班級
def delete_class(request):
    # 根據班級的ID刪除
    # 班級ID從哪兒來?  --> 須要頁面發起請求的時候攜帶
    # 頁面如何攜帶要刪除的班級的ID? --> 經過給a標籤設置href屬性時拼接 
    # 後端拿到要刪除的班級的ID
    class_id = request.GET.get("class_id")
    # 去數據庫裏刪除
    # 鏈接數據庫
    conn = pymysql.connect(host="localhost", user="root", password="root1234", database="s8", charset="utf8")
    # 指定輸出的每條數據的類型是字典
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 刪除操做的SQL語句
    sql = "delete from class where id=%s;"
    # 執行刪除語句
    cursor.execute(sql, class_id)
    # 向數據庫提交操做
    conn.commit()
    cursor.close()
    conn.close()
    # 執行完刪除操做後跳轉回班級列表頁面
    return redirect("/class_list/")
複製代碼

頁面部分

瀏覽器發起的GET請求經過在URL後面添加/url/?k1=v1&k2=v2的方式添加參數。

使用Django模板語言的語法將{{ class.id }}拼接到了a標籤的href屬性中。

這樣頁面點擊這個a標籤就能把要刪除的班級ID值傳遞給後端了

<a href="/delete_class/?class_id={{ class.id }}" type="button" class="btn btn-sm btn-danger" aria-label="Left Align">
  <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>刪除
</a>

添加班級

後端部分

複製代碼
# 添加班級
def add_class(request):
    # 若是是POST請求,就代表是頁面要提交數據
    if request.method == "POST":
        # 頁面使用POST方法提交添加班級的數據
        # 後端取到新班級的名稱信息
        class_name = request.POST.get("cname")
        conn = pymysql.connect(host="localhost", user="root", password="root1234", database="s8", charset="utf8")
        # 指定輸出的結果類型是字典
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 新增班級的SQL語句
        sql = "insert into class (cname) VALUE (%s);"
        # 執行SQL語句,在數據庫中建立一條新的班級記錄
        cursor.execute(sql, class_name)
        # 向數據庫提交
        conn.commit()
        # 關閉鏈接
        cursor.close()
        conn.close()
        # 新添加一個班級以後跳轉到班級列表頁面
        return redirect("/class_list/")
    # 若是不是POST請求就返回添加班級頁面
    return render(request, "add_class.html")
複製代碼

頁面部分

利用form表單向後端提交新班級的數據,因此add_class.html頁面中form表單要填寫上action="/add_class/」 和 method=「post」

<form action="/add_class/" method="post">
    <input type="text" name="cname">
    <input type="submit" value="提交">
</form>

編輯班級信息

後端部分

複製代碼
# 新頁面編輯班級信息
def edit_class(request):
    # 若是是POST請求
    if request.method == "POST":
        # 從頁面POST過來的數據中取到編輯的班級ID
        class_id = request.POST.get("id")
        # 從頁面POST過來的數據中取到班級名稱
        class_cname = request.POST.get("cname")
        # 去數據庫裏面更新班級名稱
        # 鏈接數據庫
        conn = pymysql.connect(host="localhost", user="root", password="root1234", database="s8", charset="utf8")
        # 獲取光標
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 更新班級信息的SQL語句
        sql = "update class set cname=%s where id=%s;"
        # 執行SQL語句
        cursor.execute(sql,(class_cname, class_id))
        # 向數據庫提交修改
        conn.commit()
        # 關閉鏈接
        cursor.close()
        conn.close()
        # 更新完班級信息以後跳轉回班級列表頁面
        return redirect("/class_list/")

    # 若是不是POST請求,就代表是點擊了新頁面編輯班級信息的按鈕
    # 取到被編輯的班級的ID
    class_id = request.GET.get("class_id")
    # 去數據庫裏查詢當前班級的信息
    conn = pymysql.connect(host="localhost", user="root", password="root1234", database="s8", charset="utf8")
    # 指定輸出的單條數據的類型是字典
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 查詢的SQL語句
    sql = "select id, cname from class WHERE id=%s;"
    # 執行查詢操做
    cursor.execute(sql, class_id)
    # 取單條數據
    ret = cursor.fetchone()
    # 關閉鏈接
    cursor.close()
    conn.close()
    # 把要編輯的班級的信息 替換 edit_class.html 頁面中的特殊符號,最後把頁面返回給瀏覽器
    return render(request, "edit_class.html", {"class_info": ret})
複製代碼

頁面部分

編輯班級信息在頁面上展現的就是一個form表單,用戶更新完班級信息以後要提交,就須要向後端提交表單數據。

這個時候form表單就須要配置好 action="/edit_class/" 和 method="post"。

可是提交的數據裏須要告知後端,我更改的是數據庫中的哪一條班級信息,因此這裏要把班級ID也放到form表單中。

班級ID不該該讓用戶修改,因此就把班級ID的input框給隱藏掉

<form action="/edit_class/" method="post">
    <input type="text" name="id" value="{{ class_info.id }}" style="display: none">
    <input type="text" name="cname" value="{{ class_info.cname }}">
    <input type="submit" value="提交">
</form> 

學生信息管理功能開發

學生信息展現(查)

 區別於班級信息管理,學生信息由於經過外鍵關聯了班級信息,因此除了要展現學生的姓名還要展現出學生所屬班級的名稱。

後端部分

複製代碼
def student_list(request):
    conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="root1234", db="mysite", charset="utf8")
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("SELECT student.id, student.name, class.name AS class_name from student LEFT JOIN class ON student.class_id = class.id;")
    student_list = cursor.fetchall()
    cursor.close()
    conn.close()
    return render(request, "student_list.html", {"students": student_list}) 
複製代碼

前端部分

複製代碼
<table class="table table-bordered table-striped">
  <thead>
  <tr>
    <th>#</th>
    <th>學生姓名</th>
    <th>班級</th>
    <th>操做</th>
  </tr>
  </thead>
  <tbody>
  {% for student in students %}

  <tr>
    <th scope="row">{{ student.id }}</th>
    <td>{{ student.name }}</td>
    <td>{{ student.class_name }}</td>
    <td class="text-center">
      <a type="button" class="btn btn-sm btn-success" aria-label="Left Align">
        <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>編輯
      </a>
      |
      <a href="/edit_student/?student_id={{ student.id }}/" type="button" class="btn btn-sm btn-success" aria-label="Left Align">
        <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>新頁面編輯
      </a>
      |
      <a href="/delete_student/?student_id={{ student.id }}" type="button" class="btn btn-sm btn-danger" aria-label="Left Align">
        <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>刪除
      </a>
    </td>
  </tr>
  {% endfor %}

  </tbody>
</table>
複製代碼

刪除學生信息(刪) 

後端部分

複製代碼
def delete_student(request):
    # 從GET請求的URL中取到要刪除的學生ID
    student_id = request.GET.get("student_id")
    # 鏈接數據庫
    conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="root1234", db="mysite", charset="utf8")
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 刪除指定的學生
    sql = "delete from student WHERE id=%s;"
    # 執行SQL語句
    cursor.execute(sql, [student_id, ])
    conn.commit()
    conn.close()
    # 刪除成功,跳轉到學生列表頁
    return redirect("/student_list/")
複製代碼

前端部分

 注意在學生信息的頁面刪除按鈕上用模板語言的方式拼接student_id

<a href="/delete_student/?student_id={{ student.id }}" type="button" class="btn btn-sm btn-danger" aria-label="Left Align">
  <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>刪除
</a>

添加學生信息(增) 

後端部分

複製代碼
def add_student(request):
    # 若是是POST請求表示前端提交數據過來
    if request.method == "POST":
        student_name = request.POST.get("student_name")
        class_id = request.POST.get("class_id")
        conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="root1234", db="mysite", charset="utf8")
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        cursor.execute("insert into student(name, class_id) VALUES (%s, %s)", [student_name, class_id])
        conn.commit()
        cursor.close()
        conn.close()
        return redirect("/student_list/")
    # 前端不發送POST請求狀況下默認返回新增學生信息頁面
    else:
        # 由於咱們新添加學生信息的時候須要指定所屬的班級
        # 因此須要先查詢出全部的班級信息,填充到頁面上
        conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="root1234", db="mysite", charset="utf8")
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        cursor.execute("select id, name from class")
        class_list = cursor.fetchall()
        cursor.close()
        conn.close()
        return render(request, "add_student.html", {"class_list": class_list})
複製代碼

前端部分

前端頁面須要將已經有的班級信息作成能夠選擇的select框

複製代碼
<form class="form-horizontal" action="/add_student/" method="post">
  <div class="form-group">
    <label for="inputclassname" class="col-sm-2 control-label">學生姓名</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" name="student_name" id="inputclassname" placeholder="學生姓名">
    </div>
  </div>
  <div class="form-group">
    <label for="selectclass" class="col-sm-2 control-label">班級</label>
    <div class="col-sm-10">
      <select class="form-control" name="class_id">
        {% for class in class_list %}
          <option value="{{ class.id }}">{{ class.name }}</option>
        {% endfor %}
      </select>
    </div>
  </div>
  <div class="form-group">
    <div class="col-sm-offset-2 col-sm-10">
      <button type="submit" class="btn btn-default">提交</button>
    </div>
  </div>
</form>
複製代碼

編輯學生信息(改)

後端部分

複製代碼
def edit_student(request):
    if request.method == "POST":
        student_id = request.POST.get("student_id")
        student_name = request.POST.get("student_name")
        class_id = request.POST.get("class_id")
        # 更新學生表的SQL
        sql = "update student set name=%s, class_id= %s WHERE id=%s;"
        # 鏈接數據庫
        conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="root1234", db="mysite", charset="utf8")
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        cursor.execute(sql, [student_name, class_id, student_id])
        cursor.close()
        conn.close()
        # 更新完學生信息以後跳轉到學生列表頁面
        return redirect("/student_list/")
    else:
        # 要編輯學生信息就須要在頁面上把當前學生的信息以及全部的班級信息都展現出來
        # 取到要編輯的學生的ID
        student_id = request.GET.get("student_id")
        # 鏈接數據庫
        conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="root1234", db="mysite", charset="utf8")
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 取到全部的班級信息
        get_class_sql = "select id, name from class;"
        cursor.execute(get_class_sql)
        class_list = cursor.fetchall()
        get_student_sql = "select id, name, class_id from student where id=%s;"
        cursor.execute(get_student_sql, [student_id, ])
        student = cursor.fetchone()
        cursor.close()
        conn.close()
        return render(request, "edit_student.html", {"class_list": class_list, "student": student})
複製代碼

前端部分

複製代碼
<form class="form-horizontal" action="/edit_student/" method="post">
  <input type="text" name="student_id" value="{{ student.id }}" style="display: none">
  <div class="form-group">
    <label for="inputclassname" class="col-sm-2 control-label">學生姓名</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" name="student_name" id="inputclassname" placeholder="班級名稱" value="{{ student.name }}">
    </div>
    <span id="helpBlock2" class="help-block">{{ error }}</span>
  </div>
  <div class="form-group">
      <label for="selectclass" class="col-sm-2 control-label">班級</label>
      <div class="col-sm-10">
        <select class="form-control" name="class_id">
          {% for class in class_list %}
            {% if class.id == student.class_id %}
            <option selected value="{{ class.id }}">{{ class.name }}</option>
            {% else %}
            <option value="{{ class.id }}">{{ class.name }}</option>
            {% endif %}
          {% endfor %}
        </select>
      </div>
    </div>
  <div class="form-group">
    <div class="col-sm-offset-2 col-sm-10">
      <button type="submit" class="btn btn-default">提交</button>
    </div>
  </div>
</form>
複製代碼

pymysql操做數據庫優化

咱們以前使用pymysql操做數據庫的操做都是寫死在視圖函數中的,而且不少都是重複的代碼。

咱們能夠優化一下,把重複的代碼提取出來,寫成函數:

複製代碼
import pymysql

# 定義一個數據庫相關的配置項
DB_CONFIG = {
    "host": "127.0.0.1",
    "port": 3306,
    "user": "root",
    "passwd": "root1234",
    "db": "mysite",
    "charset": "utf8"
}


# 查詢多條數據函數
def get_list(sql, args=None):
    conn = pymysql.connect(
        host=DB_CONFIG["host"],
        port=DB_CONFIG["port"],
        user=DB_CONFIG["user"],
        passwd=DB_CONFIG["passwd"],
        db=DB_CONFIG["db"],
        charset=DB_CONFIG["charset"]
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute(sql, args)
    result = cursor.fetchall()
    cursor.close()
    conn.close()
    return result


# 查詢單挑數據函數
def get_one(sql, args=None):
    conn = pymysql.connect(
        host=DB_CONFIG["host"],
        port=DB_CONFIG["port"],
        user=DB_CONFIG["user"],
        passwd=DB_CONFIG["passwd"],
        db=DB_CONFIG["db"],
        charset=DB_CONFIG["charset"]
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute(sql, args)
    result = cursor.fetchone()
    cursor.close()
    conn.close()
    return result


# 修改記錄
def modify(sql, args=None):
    conn = pymysql.connect(
        host=DB_CONFIG["host"],
        port=DB_CONFIG["port"],
        user=DB_CONFIG["user"],
        passwd=DB_CONFIG["passwd"],
        db=DB_CONFIG["db"],
        charset=DB_CONFIG["charset"]
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute(sql, args)
    conn.commit()
    cursor.close()
    conn.close()


# 建立記錄
def create(sql, args=None):
    conn = pymysql.connect(
        host=DB_CONFIG["host"],
        port=DB_CONFIG["port"],
        user=DB_CONFIG["user"],
        passwd=DB_CONFIG["passwd"],
        db=DB_CONFIG["db"],
        charset=DB_CONFIG["charset"]
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute(sql, args)
    conn.commit()
    # 返回剛纔建立的那條數據的ID
    last_id = cursor.lastrowid
    cursor.close()
    conn.close()
    return last_id
複製代碼

這樣只要在須要鏈接數據庫作操做的時候,只須要調用咱們上面定義好的函數就能夠了

 

可是這樣仍是有問題,當我要大批量建立數據的時候,就須要屢次調用create方法了,至關於屢次鏈接屢次提交。

能夠繼續優化下,把數據庫的鏈接重用,作到只需一次鏈接就可執行屢次操做

複製代碼
class SQLManager(object):

    # 初始化實例方法
    def __init__(self):
        self.conn = None
        self.cursor = None
        self.connect()

    # 鏈接數據庫
    def connect(self):
        self.conn = pymysql.connect(
            host=DB_CONFIG["host"],
            port=DB_CONFIG["port"],
            user=DB_CONFIG["user"],
            passwd=DB_CONFIG["passwd"],
            db=DB_CONFIG["db"],
            charset=DB_CONFIG["charset"]
        )
        self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)

    # 查詢多條數據
    def get_list(self, sql, args=None):
        self.cursor.execute(sql, args)
        result = self.cursor.fetchall()
        return result

    # 查詢單條數據
    def get_one(self, sql, args=None):
        self.cursor.execute(sql, args)
        result = self.cursor.fetchone()
        return result

    # 執行單條SQL語句
    def moddify(self, sql, args=None):
        self.cursor.execute(sql, args)
        self.conn.commit()

    # 建立單條記錄的語句
    def create(self, sql, args=None):
        self.cursor.execute(sql, args)
        self.conn.commit()
        last_id = self.cursor.lastrowid
        return last_id

    # 關閉數據庫cursor和鏈接
    def close(self):
        self.cursor.close()
        self.conn.close()
複製代碼

咱們把咱們數據庫的相關操做都封裝成一個類,在用到的時候,只須要生成一個實例,並對實例調用相應的操做方法就能夠了。

db = SQLManager()
class_list = db.get_list("select id, name from class")
teacher_info = db.get_list("SELECT teacher.id, teacher.name, teacher2class.class_id FROM teacher  LEFT JOIN teacher2class ON teacher.id = teacher2class.teacher_id WHERE teacher.id=%s;", [teacher_id])
db.close()

可是,我若是要批量執行多個建立操做,雖然只創建了一次數據庫鏈接可是仍是會屢次提交,可不能夠改爲一次鏈接,一次提交呢?

能夠,只須要用上pymysql的executemany()方法就能夠了。

給咱們的 SQLManager類添加一個批量執行的 multi_modify()方法就能夠了。

# 執行多條SQL語句
def multi_modify(self, sql, args=None):
    self.cursor.executemany(sql, args)
    self.conn.commit()

如今咱們若是一次執行多個建立操做的話就可使用multi_modify()方法,實現一次鏈接一次提交了。

最後,咱們每次操做完數據庫以後都要手動關閉,可不能夠寫成自動關閉的呢?

聯想到咱們以前學過的文件操做,使用with語句能夠實現縮進結束自動關閉文件句柄的例子。

咱們來把咱們的數據庫鏈接類SQLManager類再優化下,使其支持with語句操做。

複製代碼
class SQLManager(object):

    # 初始化實例方法
    def __init__(self):
        self.conn = None
        self.cursor = None
        self.connect()

    # 鏈接數據庫
    def connect(self):
        self.conn = pymysql.connect(
            host=DB_CONFIG["host"],
            port=DB_CONFIG["port"],
            user=DB_CONFIG["user"],
            passwd=DB_CONFIG["passwd"],
            db=DB_CONFIG["db"],
            charset=DB_CONFIG["charset"]
        )
        self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)

    # 查詢多條數據
    def get_list(self, sql, args=None):
        self.cursor.execute(sql, args)
        result = self.cursor.fetchall()
        return result

    # 查詢單條數據
    def get_one(self, sql, args=None):
        self.cursor.execute(sql, args)
        result = self.cursor.fetchone()
        return result

    # 執行單條SQL語句
    def moddify(self, sql, args=None):
        self.cursor.execute(sql, args)
        self.conn.commit()

    # 執行多條SQL語句
    def multi_modify(self, sql, args=None):
        self.cursor.executemany(sql, args)
        self.conn.commit()

    # 建立單條記錄的語句
    def create(self, sql, args=None):
        self.cursor.execute(sql, args)
        self.conn.commit()
        last_id = self.cursor.lastrowid
        return last_id

    # 關閉數據庫cursor和鏈接
    def close(self):
        self.cursor.close()
        self.conn.close()

    # 進入with語句自動執行
    def __enter__(self):
        return self
    
    # 退出with語句塊自動執行
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()
複製代碼

現階段,咱們只須要優化到這一步就能夠,後面的項目實戰中會繼續優化。如使用數據庫鏈接池等。

老師信息管理

老師信息管理相比於學生信息管理又多了一點,由於咱們的數據結構中老師表和班級表是經過teacher2class表進行多對多關聯的。

後端部分

注意連表查詢操做

複製代碼
def magic(data_o):
    tmp = {}
    for i in data_o:
        if i["tid"] not in tmp:
            tmp[i["tid"]] = {"id": i["tid"],"tname": i["tname"], "cname": [i["cname"]]}
        else:
            tmp[i["tid"]]["cname"].append(i["cname"])
    data = list(tmp.values())
    return data


def teacher_list(request):
    # 鏈接數據庫
    conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="root1234", db="mysite", charset="utf8")
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    sql = "select teacher.id, teacher.name, class.name as cname from teacher LEFT JOIN teacher2class on teacher.id = teacher2class.teacher_id LEFT JOIN class ON teacher2class.class_id = class.id;"
    cursor.execute(sql)
    teacher_list_o = cursor.fetchall()
    # 將查詢到的數據類型轉換一下
    teacher_list = magic(teacher_list_o)
    return render(request, "teacher_list.html", {"teacher_list": teacher_list})
複製代碼

前端部分

將老師關聯的班級信息也展現出來。

複製代碼
<table class="table table-bordered table-striped">
  <thead>
  <tr>
    <th>#</th>
    <th>老師</th>
    <th>班級</th>
    <th>操做</th>
  </tr>
  </thead>
  <tbody>
  {% for teacher in teacher_list %}
  <tr>
    <th scope="row">{{ teacher.id }}</th>
    <td>{{ teacher.name }}</td>
    <td>
      {% for class in teacher.class_list %}
      <span>{{ class }}</span>|
      {% endfor %}
    </td>
    <td class="text-center">
      <a type="button" class="btn btn-sm btn-success m-edit" aria-label="Left Align">
        <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>編輯
      </a>
      |
      <a href="/edit_teacher/?teacher_id={{ teacher.id }}/" type="button" class="btn btn-sm btn-success" aria-label="Left Align">
        <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>新頁面編輯
      </a>
      |
      <a href="/delete_teacher/?teacher_id={{ teacher.id }}" type="button" class="btn btn-sm btn-danger" aria-label="Left Align">
        <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>刪除
      </a>
    </td>
  </tr>
    {% empty %}
    <tr> <td colspan="3" style="text-align: center">空空如也~</td></tr>
  {% endfor %}
  </tbody>
</table>
複製代碼

刪除老師信息

後端部分

後端從請求的URL中提取到要刪除的老師的ID。

複製代碼
def delete_teacher(request):
    # 從GET請求的URL中取到要刪除的老師ID
    teacher_id = request.GET.get("student_id")
    # 鏈接數據庫
    conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="root1234", db="mysite", charset="utf8")
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 刪除指定的老師
    sql = "delete from teacher WHERE id=%s;"
    # 執行SQL語句
    cursor.execute(sql, [teacher_id, ])
    conn.commit()
    conn.close()
    # 刪除成功,跳轉到老師列表頁
    return redirect("/teacher_list/")
複製代碼

前端部分

點擊頁面上對應老師記錄的刪除按鈕,向後端發送GET請求,將要刪除的老師的ID傳遞給後端。

刪除按鈕部分HTML代碼:

<a href="/delete_teacher/?teacher_id={{ class.id }}" type="button" class="btn btn-sm btn-danger" aria-label="Left Align">
  <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>刪除
</a>

新增老師信息

後端部分

這裏咱們對咱們的數據庫鏈接部分的代碼作了優化。

複製代碼
from tools.sql_master import create, SQLManager
def add_teacher(request):
    if request.method == "POST":
        class_list = request.POST.getlist("class_id")
        teacher_name = request.POST.get("teacher_name")
        # 建立老師
        teacher_id = create("insert into teacher(name) VALUES (%s)", [teacher_name, ])
        # 更新teacher2class表
        # 屢次連接,屢次提交
        # for i in class_list:
        #     modify("insert into teacher2class(teacher_id, class_id) VALUES (%s, %s)", [teacher_id, i])
        #
        # # 一次連接,屢次提交
        # db = SQLManager()
        # for i in class_list:
        #     db.moddify("insert into teacher2class(teacher_id, class_id) VALUES (%s, %s)", [teacher_id, i])
        # db.close()
        #
        # 一次連接,一次提交
        data_list = []
        for i in class_list:
            tmp = [teacher_id, i]
            data_list.append(tmp)
        db = SQLManager()
        db.multi_modify("insert into teacher2class(teacher_id, class_id) VALUES (%s, %s)", data_list)
        db.close()
        return redirect("/teacher_list/")
    else:
        class_list = get_list("select id, name from class")
        return render(request, "add_teacher.html", {"class_list": class_list})
複製代碼

前端部分

由於咱們添加老師信息的時候,須要給老師指定關聯的班級信息,因此在頁面上須要將現有的班級信息展現出來。

新增老師信息時,輸入老師的姓名而後選擇關聯的班級信息便可。

複製代碼
<form class="form-horizontal" action="/add_teacher/" method="post">
  <div class="form-group">
    <label for="inputclassname" class="col-sm-2 control-label">老師姓名</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" name="teacher_name" id="inputclassname" placeholder="老師姓名">
    </div>
  </div>
  <div class="form-group">
    <label for="selectclass" class="col-sm-2 control-label">班級</label>
    <div class="col-sm-10">
      <select class="form-control" name="class_id" multiple>
        {% for class in class_list %}
          <option value="{{ class.id }}">{{ class.name }}</option>
        {% endfor %}
      </select>
    </div>
  </div>
  <div class="form-group">
    <div class="col-sm-offset-2 col-sm-10">
      <button type="submit" class="btn btn-default">提交</button>
    </div>
  </div>
</form>
複製代碼

編輯老師信息

後端部分

複製代碼
def edit_teacher(request):
    if request.method == "POST":
        teacher_id = request.POST.get("teacher_id")
        class_ids = request.POST.getlist("class_id")
        # 更新
        db = SQLManager()
        teacher_class_ids = db.get_list("select class_id from teacher2class WHERE teacher_id=%s", [teacher_id, ])
        old_class_ids = [i["class_id"] for i in teacher_class_ids]
        # 粗暴更新
        del_id_list = []
        add_id_list = []
        for i in old_class_ids:
            del_id_list.append((teacher_id, i))
        for j in class_ids:
            add_id_list.append((teacher_id, j))
        db.multi_modify("DELETE from teacher2class WHERE teacher_id=%s AND class_id=%s", del_id_list)
        db.multi_modify("insert into teacher2class(teacher_id, class_id) VALUES (%s, %s)", add_id_list)
        db.close()
        return redirect("/teacher_list")
    else:
        teacher_id = request.GET.get("teacher_id")
        with SQLManager() as db:
            class_list = db.get_list("select id, name from class")
            teacher_info = db.get_list("SELECT teacher.id, teacher.name, teacher2class.class_id FROM teacher  LEFT JOIN teacher2class ON teacher.id = teacher2class.teacher_id WHERE teacher.id=%s;", [teacher_id])
        ret = teacher_info[0]
        ret["class_ids"] = [ret["class_id"], ]
        for i in teacher_info[1:]:
            ret["class_ids"].append(i["class_id"])
        return render(request, "edit_teacher.html", {"class_list": class_list, "teacher": ret})
複製代碼

前端部分

複製代碼
<form class="form-horizontal" action="/edit_teacher/" method="post">
  <input type="text" name="teacher_id" value="{{ teacher.id }}" style="display: none">
  <div class="form-group">
    <label for="inputclassname" class="col-sm-2 control-label">學生姓名</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" name="teacher_name" id="inputteachername" placeholder="老師姓名" value="{{ teacher.name }}">
    </div>
    <span id="helpBlock2" class="help-block">{{ error }}</span>
  </div>
  <div class="form-group">
      <label for="selectclass" class="col-sm-2 control-label">班級</label>
      <div class="col-sm-10">
        <select class="form-control" name="class_id" multiple>
          {% for class in class_list %}
            {% if class.id in teacher.class_ids %}
            <option selected value="{{ class.id }}">{{ class.name }}</option>
            {% else %}
            <option value="{{ class.id }}">{{ class.name }}</option>
            {% endif %}
          {% endfor %}
        </select>
      </div>
    </div>
  <div class="form-group">
    <div class="col-sm-offset-2 col-sm-10">
      <button type="submit" class="btn btn-default">提交</button>
    </div>
  </div>
</form>
相關文章
相關標籤/搜索