通過django開發一個簡單后台管理系統,主要運用django、前端相關知識。本文主要記錄一步一步實現過程
一、創建項目
創建project django-admin startproject user_manager 創建APP python manage.py startapp app01
二、設計表結構
主要有班級表、老師表、學生表、用戶表。班級和學生是一對多的關系、班級和老師是多對多的關系。

from django.db import models # Create your models here. class Classes(models.Model): caption = models.CharField(max_length=32) class Student(models.Model): name = models.CharField(max_length=32) cls = models.ForeignKey(Classes,on_delete=models.CASCADE) class Teacher(models.Model): name = models.CharField(max_length=32) cls = models.ManyToManyField(Classes) class Administrator(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32)
生成同步數據庫的腳本
python manage.py makemigrations
同步數據庫
python manage.py migrate
三、相關功能實現
1、登錄注冊
用戶訪問登錄url,返回登錄頁面,輸入用戶名/密碼,驗證通過,返回首頁;驗證失敗,提示錯誤信息。用戶未登錄直接訪問首頁url,重定向到登錄頁面(其中會用到cookie和session相關知識)
url設計

from django.contrib import admin from django.urls import path from django.conf.urls import include, url from app01.views import * urlpatterns = [ path('admin/', admin.site.urls), url(r'^login/', login), #登錄url url(r'^index/', index), #首頁url ]
登錄頁面/首頁頁面/視圖函數

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="login.html" method="post"> {% csrf_token %} <div> <label for="user"> 用戶名:</label> <input id="user" type="text" name="user"> </div> <div> <label for="pwd"> 密 碼:</label> <input id="pwd" type="password" name="pwd"> </div> <div> <label></label> <input type="submit" value="登錄"> <span style="color: red">{{ msg }}</span> </div> </form> </body> </html>

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>hell {{ user }}</p> </body> </html>

from django.shortcuts import render # Create your views here. from django.shortcuts import redirect from django.http import HttpResponse from django.views.decorators import csrf import json import requests import re import os from app01.models import * #from django.contrib.sessions.backends.db import SessionStore def login(request): message = '' print(request.COOKIES) """{'_ga': 'GA1.1.664909549.1531444385', 'csrftoken': 'cH0jMqG7OmrbRcSoOD6FdNTgGdVdFOvRl6x3gH74GnkTFLdxyNAifvoVDiGkinWi', 'sessionid': 'wd7pa91lltnnxe7qjet6uxe3tuyb32jz', 'username': 'root'}""" #v = request.session #request.session.clear() if request.method == "POST": print(request.POST) user = request.POST.get('user') pwd = request.POST.get('pwd') '''if user == 'root' and pwd == '123': rep = redirect('/index') # 將username寫入瀏覽器cookie,失效時間為60s rep.set_cookie('username',user,60) return rep''' #從數據庫中查詢用戶和密碼是否正確 num=Administrator.objects.filter(username=user,password=pwd).count() if num: rep = redirect('/index') rep.set_cookie('username', user, 60) #request.session['is_login'] = True #request.session['username'] = user return rep else: message = '用戶或密碼錯誤' return render(request, 'login.html',{'msg':message}) def index(request): #如果用戶已經登錄獲取用戶,否則返回登錄頁面,禁止用戶直接訪問index頁面 # 通過cookie判斷用戶是否已登錄,提取瀏覽器中的cookie,如果不為空,表示已經登錄 user = request.COOKIES.get('username') #user = request.session.get('username') if user: return render(request,'index.html',{'user':user}) else: return redirect('/login')
cookie和session學

1、cookie是什么? -是存儲在客戶端瀏覽器上的鍵值對,作用是記錄狀態 -原理:是服務器產生,發給客戶端瀏覽器,瀏覽器保存起來,下次發請求,會攜帶這個鍵值對到服務器 -Cookie的覆蓋:先寫了一個鍵值對,后來再寫,會把原來的值覆蓋掉 2、cookie的使用 -設置cookie:在HttpResponse這個對象上寫(render, redirect,JsonResponse繼承了HttpResponse,均可以設置cookie) -obj.set_cookie(key,value) -取cookie:從request對象中取,取出來是個字典request.COOKIES request.COOKIES.get('name') -刪除cookie: obj.delete_cookie('name') 3、cookie的其他屬性 加密鹽 obj.set_cookie(key,value) obj.set_signed_cookie(key,value,salt='加密鹽') •max_age=5, 超時時間,5秒后失效, cookie需要延續的時間(以秒為單位)如果參數是‘None’,這個cookie會延續到瀏覽器關閉為止 •expires,超時時間,傳一個datatime對象 •path='/', 可以設置路徑,設置路徑之后,-obj.set_cookie(key,value,path='/index/'),只有訪問index的時候,才會攜帶cookie過來,設置根路徑表示所有請求都會攜帶 •domain=None, Cookie生效的域名 你可用這個參數來構造一個跨站cookie。如, domain=".example.com"所構造的cookie對下面這些站點都是可讀的:www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。如果該參數設置為 None ,cookie只能由設置它的站點讀取 •secure=False, 默認是false,設置成True瀏覽器將通過HTTPS來回傳cookie •httponly=False 只能http協議傳輸,無法被JavaScript獲取(不是絕對,底層抓包可以獲取到也可以被覆蓋)

Cookie雖然在一定程度上解決了“保持狀態”的需求,但是由於Cookie本身最大支持4096字節,以及Cookie本身保存在客戶端,可能被攔截或竊取,因此就需要有一種新的東西,它能支持更多的字節,並且他保存在服務器,有較高的安全性。這就是Session 1、session: - 存在服務器上的鍵值對,key是一個隨機的字符串,value是一個字典,比如:{'sdaf隨機字符串':{name:lww,pwd:123}} -解決cookie不安全的問題,客戶端瀏覽器上不再存儲敏感的信息 -如果設置多個,它會以字典的形式存儲到session表中的session_data中 -生成session時:request.session['name']='lww' 原理: 1 生成隨機字符串,如:koerjkdfssl 2 存到數據庫,隨機字符串是一個字段,{'name':'lww'}是一個字段 3 寫入cookie(set_cookie('sessionid','koerjkdfssl')) -取值 - name=request.session['name'] -執行流程: -取到cookie的隨機字符串 -去session表中根據隨機字符串查詢,查詢出session_data這個字典,然后重字典中取出name對應的值 -刪除值 -# 取出cookie,隨機字符串,去數據庫刪除隨機字符串是當前值的記錄 request.session.delete() -#既刪除cookie,又刪除數據庫 request.session.flush()
Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:數據庫(默認)、緩存、文件、緩存+數據庫、加密cookie

Django默認支持Session,並且默認是將Session數據存儲在數據庫中,即:django_session 表中。 a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默認) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑(默認) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默認) SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie(默認) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸(默認) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默認) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過期(默認) SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認修改之后才保存(默認) b. 使用 # 獲取、設置、刪除Session中數據 request.session['k1'] request.session.get('k1',None) request.session['k1'] = 123 request.session.setdefault('k1',123) # 存在則不設置 del request.session['k1'] # 所有 鍵、值、鍵值對 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems() # 用戶session的隨機字符串 request.session.session_key # 將所有Session失效日期小於當前日期的數據刪除 request.session.clear_expired() # 檢查 用戶session的隨機字符串 在數據庫中是否 request.session.exists("session_key") # 刪除當前用戶的所有Session數據 request.session.delete("session_key")
通過裝飾器實現判斷用戶是否登錄

def auth(func): def inner(request, *args, **kwargs): is_login = request.session.get('is_login') if is_login: return func(request, *args, **kwargs) else: return redirect('/login') return inner @auth def index(request): current_user = request.session.get('username') return render(request, 'index.html',{'user': current_user}) #執行index函數即index() 因index函數經過裝飾器裝飾過的函數,index=auth(index)
編寫簡單的班級、學生、老師頁面

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>當前登錄用戶:{{ username }}</h1> </body> </html>

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>當前登錄用戶:{{ username }}</h1> </body> </html>

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>當前登錄用戶:{{ username }}</h1> </body> </html>
目前為止完整視圖函數代碼

from django.shortcuts import render # Create your views here. from django.shortcuts import redirect from django.http import HttpResponse from django.views.decorators import csrf import json import requests import re import os from app01.models import * from django.contrib.sessions.backends.db import SessionStore def login(request): message = '' #print(request.COOKIES) #v = request.session #print(request.session) #print(request.session.keys()) #request.session.clear() if request.method == "POST": print(request.POST) user = request.POST.get('user') pwd = request.POST.get('pwd') '''if user == 'root' and pwd == '123': rep = redirect('/index') # 將username寫入瀏覽器cookie,失效時間為60s rep.set_cookie('username',user,60) return rep''' #從數據庫中查詢用戶和密碼是否正確 num=Administrator.objects.filter(username=user,password=pwd).count() if num: rep = redirect('/index') #rep.set_cookie('username', user, 60) request.session['is_login'] = True request.session['username'] = user return rep else: message = '用戶或密碼錯誤' return render(request, 'login.html',{'msg':message}) def logout(request): request.session.clear() return redirect('/login') def auth(func): def inner(request, *args, **kwargs): is_login = request.session.get('is_login') if is_login: return func(request, *args, **kwargs) else: return redirect('/login') return inner """def index(request): #如果用戶已經登錄獲取用戶,否則返回登錄頁面,禁止用戶直接訪問index頁面 # 通過cookie判斷用戶是否已登錄,提取瀏覽器中的cookie,如果不為空,表示已經登錄 #user = request.COOKIES.get('username') user = request.session.get('username') if user: return render(request,'index.html',{'user':user}) else: return redirect('/login')""" @auth def index(request): current_user = request.session.get('username') return render(request, 'index.html',{'user': current_user}) #執行index函數即index() 因index函數經過裝飾器裝飾過的函數,index=auth(index) @auth def handle_classes(request): current_user = request.session.get('username') return render(request, 'classes.html', {'username': current_user}) def handle_student(request): is_login = request.session.get('is_login') if is_login: current_user = request.session.get('username') return render(request, 'student.html', {'username': current_user}) else: return redirect('/login') def handle_teacher(request): is_login = request.session.get('is_login') if is_login: current_user = request.session.get('username') return render(request, 'teacher.html', {'username': current_user}) else: return redirect('/login')
四、django視圖函數中兩種方式
django 視圖 分為兩種: 1. FBV 基於函數的視圖 function based view 2. CBV 基於類的視圖 class based view

CBV :基於 類的視圖函數 后端邏輯處理時不用通過邏輯,來判斷請求方式是get還是post請求在視圖類中,定義了get方法就是寫get請求的邏輯,定義類post方法時就是post請求邏輯。 類視圖的好處: 代碼可讀性好 類視圖相對於函數視圖有更高的復用性, 如果其他地方需要用到某個類視圖的某個特定邏輯,直接繼承該類視圖即可 例子: class RegisterView(View): """類視圖:處理注冊""" def get(self, request): """處理GET請求,返回注冊頁面""" return render(request, 'register.html') def post(self, request): """處理POST請求,實現注冊邏輯""" return HttpResponse('這里實現注冊邏輯')

---------url配置------------------ url(r'^login.html/', Login.as_view()), #Login 類名 ,as_view()類方法 -------------類的寫法-------------- #CBV方式 class Login(views.View): def get(self,request,*args,**kwargs): return render(request, 'login.html', {'msg': ''}) def post(self, request, *args, **kwargs): user = request.POST.get('user') pwd = request.POST.get('pwd') num = Administrator.objects.filter(username=user, password=pwd).count() if num: request.session['is_login'] = True request.session['username'] = user rep = redirect('/index') return rep else: message = '用戶或密碼錯誤' return render(request, 'login.html', {'msg': message}) -----------添加裝飾器------------- 假設裝飾器函數名為test # 直接添加在dispatch里面,這樣每個函數都會執行裝飾器方法: from django.utils.decorators import method_decorator @method_decorator(test) # 每個函數都裝飾 def dispatch(self, request, *args, **kwargs): res = super(IndexView, self).dispatch(request, *args, **kwargs) return res # 添加在每一個函數中: from django.utils.decorators import method_decorator @method_decorator(test) # 單獨指定裝飾器方法 def get(self, request, *args, **kwargs): return render(request, 'index.html') # 直接添加在類上,后面的name表示只給get添加裝飾器 from django.utils.decorators import method_decorator @method_decorator(test, name='get') get是給get方法加 (以這種方式如果想給多個方法加裝飾器,需要寫多層裝飾器,因為name這個參數的值必須是個字符串,並且不能同時寫兩個方法) 例子: @method_decorator(login_test, name='post') post是給post方法加 class IndexView(View): def get(self,request): pass def post(self,request): pass
五、模板使用

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .hide{ display: none; } .menu .item{ display: block; padding: 5px 10px; border-bottom: 1px solid #dddddd; } .menu .item:hover{ background-color: black; color: white; } .menu .item.active{ background-color: black; color: white; } /*設置添加彈出框樣式*/ .modal{ position: fixed; top: 50%; left: 50%; width: 500px; height: 400px; margin-top: -250px; margin-left: -250px; z-index: 100; background-color: white; } /*設置刪除彈出框樣式*/ .remove{ position: fixed; top: 50%; left: 50%; width: 400px; height: 200px; margin-top: -100px; margin-left: -200px; z-index: 100; background-color: white; } /*設置遮罩層樣式*/ .shade{ position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: black; opacity: 0.5; z-index: 99; } </style> {% block css %} {% endblock %} </head> <body> <div style="height: 48px;background-color: black;color: white"> <div style="float: right">用戶名:{{ username }} | <a href="/logout">注銷</a></div> </div> <div> <div class="menu" style="position: absolute;top: 48px;left: 0;bottom:0;width: 200px;background-color: #eeeeee"> <a id="menu_class" class="item" href="/classes">班級管理</a> <a id="menu_student" class="item" href="/student">學生管理</a> <a id="menu_teacher" class="item" href="/teacher">老師管理</a> </div> <div style="position: absolute;top: 48px;left: 200px;bottom:0;right: 0;overflow: auto"> {% block content %} {% endblock %} </div> </div> <script src="/static/jquery-3.1.1.js"></script> {% block js %} {% endblock %} </body> </html>

{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
老師列表
{% endblock %}
{% block js %}
{% endblock %}

{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
學生列表
{% endblock %}
{% block js %}
{% endblock %}

{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
班級列表
{% endblock %}
{% block js %}
{% endblock %}
六、班級管理
6、1 增加數據
向后台添加班級數據方式
1、模態對話框(操作數據少時一般使用)
form表單方式 : 缺點,無法顯示錯誤信息
Ajax方式提交 :
- 有錯誤,顯示錯誤;無錯誤,通過js的 location.relad() 刷新頁面
- 有錯誤,顯示錯誤;無錯誤,自己局部添加
2、單獨頁面(數據多,數據大操作):
form表單方式
通過模態對話框及ajax方式提交數據

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .hide{ display: none; } .menu .item{ display: block; padding: 5px 10px; border-bottom: 1px solid #dddddd; } .menu .item:hover{ background-color: black; color: white; } .menu .item.active{ background-color: black; color: white; } /*設置添加彈出框樣式*/ .modal{ position: fixed; top: 50%; left: 50%; width: 500px; height: 400px; margin-top: -250px; margin-left: -250px; z-index: 100; background-color: white; } /*設置刪除彈出框樣式*/ .remove{ position: fixed; top: 50%; left: 50%; width: 400px; height: 200px; margin-top: -100px; margin-left: -200px; z-index: 100; background-color: white; } /*設置遮罩層樣式*/ .shade{ position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: black; opacity: 0.5; z-index: 99; } </style> {% block css %} {% endblock %} </head> <body> <div style="height: 48px;background-color: black;color: white"> <div style="float: right">用戶名:{{ username }} | <a href="/logout">注銷</a></div> </div> <div> <div class="menu" style="position: absolute;top: 48px;left: 0;bottom:0;width: 200px;background-color: #eeeeee"> <a id="menu_class" class="item" href="/classes">班級管理</a> <a id="menu_student" class="item" href="/student">學生管理</a> <a id="menu_teacher" class="item" href="/teacher">老師管理</a> </div> <div style="position: absolute;top: 48px;left: 200px;bottom:0;right: 0;overflow: auto"> {% block content %} {% endblock %} </div> </div> <script src="/static/jquery-3.1.1.js"></script> {% block js %} {% endblock %} </body> </html>

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>班級列表</h1> <div> <input id="id_add" type="button" value="添加" /> </div> <table border="1"> <thead> <tr> <th>ID</th> <th>標題</th> <th>操作</th> </tr> </thead> <tbody> {% for item in cls_list %} <tr> <td>{{ item.id }}</td> <td>{{ item.caption }}</td> <td> <a>編輯</a> | <a class="td-delete">刪除</a> </td> </tr> {% endfor %} </tbody> </table> <div class="modal hide"> <input name="caption" type="text" placeholder="標題" /> <input id="id_modal_cancel" type="button" value="取消"/> <input type="button" id="modal_ajax_submit" value="Ajax確定"/> </div> <div class="shade hide"></div> <div class="remove hide"> <input id="id_remove_cancel" type="button" value="取消"/> <input type="button" value="確定"/> </div> {% endblock %} {% block js %} <script> $(function () { $('#menu_class').addClass('active'); bindAddEvent(); bindCancelEvent() bindTdDeleteEvent(); bindSubmitModal(); }); function bindAddEvent() { $('#id_add').click(function () { $('.modal,.shade').removeClass('hide'); }); } function bindCancelEvent() { $('#id_modal_cancel,#id_remove_cancel').click(function () { $('.modal,.shade,.remove').addClass('hide'); }); } function bindTdDeleteEvent() { /* $('td .td-delete').click(function () { $('.remove,.shade').removeClass('hide'); }) */ $('tbody').on('click', '.td-delete', function () { $('.remove,.shade').removeClass('hide'); }) } function bindSubmitModal() { $('#modal_ajax_submit').click(function () { /*獲取輸入班級的值*/ var value = $('.modal input[name="caption"]').val(); $.ajax({ url: "/classes", type: 'POST', data: {caption: value}, dataType: "JSON", success: function (rep) { //data = JSON.parse(data); if(!rep.status){ alert(rep.error); }else{ //location.reload(); /*重新載入當前頁面,類似於瀏覽器上的刷新頁面按鈕*/ //如果不刷新整個頁面,可以通過js在table表格最后追加一行數據,追加的數據就是當前增加的數據 var tr = document.createElement('tr'); var td1 = document.createElement('td'); // td1ID td1.innerHTML = rep.data.id; var td2 = document.createElement('td'); // td2標題 td2.innerHTML = rep.data.caption; var td3 = document.createElement('td'); td3.innerText = "|"; var a1 = document.createElement('a'); a1.innerHTML = "編輯"; var a2 = document.createElement('a'); a2.className = "td-delete"; a2.innerHTML = "刪除"; $(td3).prepend(a1); $(td3).append(a2); $(tr).append(td1); $(tr).append(td2); $(tr).append(td3); $('table tbody').append(tr); /*為彈出框添加hide的css樣式,及隱藏模態對話框*/ $('.modal,.shade').addClass('hide'); } } }) }) } </script> {% endblock %}

from django.shortcuts import render # Create your views here. from django.shortcuts import redirect from django.http import HttpResponse from django.views.decorators import csrf import json import requests import re import os from app01.models import * from django.contrib.sessions.backends.db import SessionStore from django import views from django.utils.decorators import method_decorator import json #CBV方式 class Login(views.View): def get(self,request,*args,**kwargs): return render(request, 'login.html', {'msg': ''}) def post(self, request, *args, **kwargs): user = request.POST.get('user') pwd = request.POST.get('pwd') num = Administrator.objects.filter(username=user, password=pwd).count() if num: request.session['is_login'] = True request.session['username'] = user rep = redirect('/index') return rep else: message = '用戶或密碼錯誤' return render(request, 'login.html', {'msg': message}) def login(request): message = '' #print(request.COOKIES) #v = request.session #print(request.session) #print(request.session.keys()) #request.session.clear() if request.method == "POST": print(request.POST) user = request.POST.get('user') pwd = request.POST.get('pwd') '''if user == 'root' and pwd == '123': rep = redirect('/index') # 將username寫入瀏覽器cookie,失效時間為60s rep.set_cookie('username',user,60) return rep''' #從數據庫中查詢用戶和密碼是否正確 num=Administrator.objects.filter(username=user,password=pwd).count() if num: rep = redirect('/index') #rep.set_cookie('username', user, 60) request.session['is_login'] = True request.session['username'] = user return rep else: message = '用戶或密碼錯誤' return render(request, 'login.html',{'msg':message}) def logout(request): request.session.clear() return redirect('/login') def auth(func): def inner(request, *args, **kwargs): is_login = request.session.get('is_login') if is_login: return func(request, *args, **kwargs) else: return redirect('/login') return inner """def index(request): #如果用戶已經登錄獲取用戶,否則返回登錄頁面,禁止用戶直接訪問index頁面 # 通過cookie判斷用戶是否已登錄,提取瀏覽器中的cookie,如果不為空,表示已經登錄 #user = request.COOKIES.get('username') user = request.session.get('username') if user: return render(request,'index.html',{'user':user}) else: return redirect('/login')""" @auth def index(request): current_user = request.session.get('username') #return render(request, 'index.html',{'user': current_user}) return render(request, 'base.html', {'username': current_user}) #執行index函數即index() 因index函數經過裝飾器裝飾過的函數,index=auth(index) @auth def handle_classes(request): if request.method == "GET": current_user = request.session.get('username') cls_list = Classes.objects.all() return render(request, 'classes.html', {'username': current_user,'cls_list': cls_list}) # 處理前端通過ajax方式提交過來數據 elif request.method == "POST": #設置字典存放信息,傳送到前端,前端根據返回信息不同做相應處理 response_dict = {'status': True, 'error': None, 'data': None} caption_name = request.POST.get('caption', None) if caption_name: obj = Classes.objects.create(caption=caption_name) #obj 是一個類Classes object (5), obj.id是添加后自增id ,obj.caption是班級名稱 #print(obj.id,obj.caption) response_dict['data'] = {"id": obj.id, "caption": obj.caption} else: response_dict['status'] = False response_dict['error'] = "標題不能為空" return HttpResponse(json.dumps(response_dict)) def handle_student(request): is_login = request.session.get('is_login') if is_login: current_user = request.session.get('username') return render(request, 'student.html', {'username': current_user}) else: return redirect('/login') def handle_teacher(request): is_login = request.session.get('is_login') if is_login: current_user = request.session.get('username') return render(request, 'teacher.html', {'username': current_user}) else: return redirect('/login')
通過跳轉到一個新的添加頁面添加信息
---------url.py----------- url(r'^add_classes', handle_add_classes),

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>添加班級</h1> <form action="/add_classes" method="POST"> <input type="text" name="caption" /> <input type="submit" value="提交"/>{{ msg }} </form> {% endblock %} {% block js %} <script> $(function () { $('#menu_class').addClass('active'); }); </script> {% endblock %}

#處理通過新的頁面添加班級信息提交過來的數據 @auth def handle_add_classes(resquest): message = "" if resquest.method == "GET": return render(resquest,"add_classes.html",{'msg':message}) elif resquest.method == "POST": caption = resquest.POST.get("caption",None) if caption: Classes.objects.create(caption=caption) else: message = "標題不能為空" return render(resquest, "add_classes.html", {'msg': message}) return redirect("/classes") else: return redirect("/index")
分頁實現

@auth def handle_classes(request): if request.method == "GET": """ #返回所有色數據 current_user = request.session.get('username') #從數據庫中獲取信息 cls_list = Classes.objects.all() return render(request, 'classes.html', {'username': current_user,'cls_list': cls_list}) """ """ 初步實現分頁功能 10:每頁顯示10條數據 current_page:當前頁頁碼 start:起始頁碼 end: 結束頁碼 cls_list:從數據庫中獲取的部分數據 total_count:數據庫中總數 v:總頁數 pager_list:存放處理后帶html代碼(一些a標簽)列表 """ current_page = request.GET.get('p', 1) current_page = int(current_page) start = (current_page - 1) * 10 end = current_page * 10 cls_list = Classes.objects.all()[start:end] total_count = Classes.objects.all().count() pager_list = [] #計算一共多少頁 v表示總頁數 v, a = divmod(total_count, 10) if a != 0: v += 1 pager_list.append('<a href="/classes?p=%s">上一頁</a>' % (current_page - 1,)) for i in range(1,v+1): if i == current_page: #為當前頁加acative樣式 pager_list.append('<a class="pageactive" href="/classes?p=%s">%s</a>' % (i, i,)) else: pager_list.append('<a href="/classes?p=%s">%s</a>' % (i, i,)) pager_list.append('<a href="/classes?p=%s">下一頁</a>' % (current_page + 1,)) pager = "".join(pager_list) # mark_safe(pager) #print(pager) current_user = request.session.get('username') return render(request, 'classes.html', {'username': current_user, 'cls_list': cls_list, 'str_pager': pager}) # 處理前端通過ajax方式提交過來數據 elif request.method == "POST": #設置字典存放信息,傳送到前端,前端根據返回信息不同做相應處理 response_dict = {'status': True, 'error': None, 'data': None} caption_name = request.POST.get('caption', None) if caption_name: obj = Classes.objects.create(caption=caption_name) #obj 是一個類Classes object (5), obj.id是添加后自增id ,obj.caption是班級名稱 #print(obj.id,obj.caption) response_dict['data'] = {"id": obj.id, "caption": obj.caption} else: response_dict['status'] = False response_dict['error'] = "標題不能為空" return HttpResponse(json.dumps(response_dict))

.pageactive{ background-color: #2e6ab1; border: 1px solid #000080; color: #fff; font-weight: bold; margin: 0 1px; padding: 1px 1px; }
分頁功能優化(封裝類的方式實現)

""" 類的方式實現分類 total_count: 數據庫中記錄總數 current_page:當前頁碼 per_page:每頁顯示記錄數 base_url:a標簽中url 如:/classes @property裝飾器就是負責把一個方法變成屬性調用的 db_start函數用來獲取起始頁碼 db_end函數用來獲取結束頁碼 total_page函數用來獲取總頁數 pager_str函數處理帶a標簽的html代碼 """ class PagerHelper: def __init__(self,total_count,current_page,base_url,per_page=10): self.total_count = total_count self.current_page = current_page self.base_url = base_url self.per_page = per_page @property def db_start(self): return (self.current_page -1) * self.per_page @property def db_end(self): return self.current_page * self.per_page def total_page(self): v, a = divmod(self.total_count, self.per_page) if a != 0: v += 1 return v def pager_str(self): v = self.total_page() pager_list = [] if self.current_page == 1: pager_list.append('<a href="javascript:void(0);">上一頁</a>') else: pager_list.append('<a href="%s?p=%s">上一頁</a>' % (self.base_url, self.current_page - 1,)) # 6,1:12 # 7,2:13 if v <= 11: pager_range_start = 1 pager_range_end = v else: if self.current_page < 6: pager_range_start = 1 pager_range_end = 11 + 1 else: pager_range_start = self.current_page - 5 pager_range_end = self.current_page + 5 + 1 if pager_range_end > v: pager_range_start = v - 10 pager_range_end = v + 1 for i in range(pager_range_start, pager_range_end): if i == self.current_page: pager_list.append('<a class="pageactive" href="%s?p=%s">%s</a>' % (self.base_url, i, i,)) else: pager_list.append('<a href="%s?p=%s">%s</a>' % (self.base_url, i, i,)) if self.current_page == v: pager_list.append('<a href="javascript:void(0);">下一頁</a>') else: pager_list.append('<a href="%s?p=%s">下一頁</a>' % (self.base_url, self.current_page + 1,)) pager = "".join(pager_list) return pager

@auth def handle_classes(request): if request.method == "GET": """ #返回所有色數據 current_user = request.session.get('username') #從數據庫中獲取信息 cls_list = Classes.objects.all() return render(request, 'classes.html', {'username': current_user,'cls_list': cls_list}) """ """ '''初步實現分頁功能 10:每頁顯示10條數據 current_page:當前頁頁碼 start:起始頁碼 end: 結束頁碼 cls_list:從數據庫中獲取的部分數據 total_count:數據庫中總數 v:總頁數 pager_list:存放處理后帶html代碼(一些a標簽)列表 ''' #第一次請求p=1 current_page = request.GET.get('p', 1) current_page = int(current_page) start = (current_page - 1) * 10 end = current_page * 10 cls_list = Classes.objects.all()[start:end] total_count = Classes.objects.all().count() pager_list = [] #計算一共多少頁 v表示總頁數 v, a = divmod(total_count, 10) if a != 0: v += 1 pager_list.append('<a href="/classes?p=%s">上一頁</a>' % (current_page - 1,)) for i in range(1,v+1): if i == current_page: #為當前頁加acative樣式 pager_list.append('<a class="pageactive" href="/classes?p=%s">%s</a>' % (i, i,)) else: pager_list.append('<a href="/classes?p=%s">%s</a>' % (i, i,)) pager_list.append('<a href="/classes?p=%s">下一頁</a>' % (current_page + 1,)) pager = "".join(pager_list) # mark_safe(pager) #print(pager) """ #封裝類的方式實現分頁 from utils.page import PagerHelper current_page = request.GET.get('p', 1) current_page = int(current_page) total_count = Classes.objects.all().count() obj = PagerHelper(total_count, current_page, '/classes',10) cls_list = Classes.objects.all()[obj.db_start:obj.db_end] pager = obj.pager_str() current_user = request.session.get('username') return render(request, 'classes.html', {'username': current_user, 'cls_list': cls_list, 'str_pager': pager}) # 處理前端通過ajax方式提交過來數據 elif request.method == "POST": #設置字典存放信息,傳送到前端,前端根據返回信息不同做相應處理 response_dict = {'status': True, 'error': None, 'data': None} caption_name = request.POST.get('caption', None) if caption_name: obj = Classes.objects.create(caption=caption_name) #obj 是一個類Classes object (5), obj.id是添加后自增id ,obj.caption是班級名稱 #print(obj.id,obj.caption) response_dict['data'] = {"id": obj.id, "caption": obj.caption} else: response_dict['status'] = False response_dict['error'] = "標題不能為空" return HttpResponse(json.dumps(response_dict)) views.py
編輯班級信息

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>班級列表</h1> <div> <input id="id_add" type="button" value="添加" /> <!--通過新的頁面添加數據,用戶點擊添加跳轉到添加班級信息的頁面--> <a href="/add_classes">添加</a> </div> <table border="1"> <thead> <tr> <th>ID</th> <th>標題</th> <th>操作</th> </tr> </thead> <tbody> {% for item in cls_list %} <tr> <td>{{ item.id }}</td> <td>{{ item.caption }}</td> <td> <a target="_blank" href="/edit_classes?nid={{ item.id }}">編輯</a> | <a class="td-delete">刪除</a> </td> </tr> {% endfor %} </tbody> </table> <div class="pagination"> {{ str_pager|safe }} </div> <div class="modal hide"> <input name="caption" type="text" placeholder="標題" /> <input id="id_modal_cancel" type="button" value="取消"/> <input type="button" id="modal_ajax_submit" value="Ajax確定"/> </div> <div class="shade hide"></div> <div class="remove hide"> <input id="id_remove_cancel" type="button" value="取消"/> <input type="button" value="確定"/> </div> {% endblock %} {% block js %} <script> $(function () { $('#menu_class').addClass('active'); bindAddEvent(); bindCancelEvent() bindTdDeleteEvent(); bindSubmitModal(); }); function bindAddEvent() { $('#id_add').click(function () { $('.modal,.shade').removeClass('hide'); }); } function bindCancelEvent() { $('#id_modal_cancel,#id_remove_cancel').click(function () { $('.modal,.shade,.remove').addClass('hide'); }); } function bindTdDeleteEvent() { /* $('td .td-delete').click(function () { $('.remove,.shade').removeClass('hide'); }) */ $('tbody').on('click', '.td-delete', function () { $('.remove,.shade').removeClass('hide'); }) } function bindSubmitModal() { $('#modal_ajax_submit').click(function () { /*獲取輸入班級的值*/ var value = $('.modal input[name="caption"]').val(); $.ajax({ url: "/classes", type: 'POST', data: {caption: value}, dataType: "JSON", success: function (rep) { //data = JSON.parse(data); if(!rep.status){ alert(rep.error); }else{ //location.reload(); /*重新載入當前頁面,類似於瀏覽器上的刷新頁面按鈕*/ //如果不刷新整個頁面,可以通過js在table表格最后追加一行數據,追加的數據就是當前增加的數據 var tr = document.createElement('tr'); var td1 = document.createElement('td'); // td1ID td1.innerHTML = rep.data.id; var td2 = document.createElement('td'); // td2標題 td2.innerHTML = rep.data.caption; var td3 = document.createElement('td'); td3.innerText = "|"; var a1 = document.createElement('a'); a1.innerHTML = "編輯"; var a2 = document.createElement('a'); a2.className = "td-delete"; a2.innerHTML = "刪除"; $(td3).prepend(a1); $(td3).append(a2); $(tr).append(td1); $(tr).append(td2); $(tr).append(td3); $('table tbody').append(tr); /*為彈出框添加hide的css樣式,及隱藏模態對話框*/ $('.modal,.shade').addClass('hide'); } } }) }) } </script> {% endblock %}

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>添加班級</h1> <form action="/add_classes" method="POST"> <input type="text" name="caption" /> <input type="submit" value="提交"/>{{ msg }} </form> {% endblock %} {% block js %} <script> $(function () { $('#menu_class').addClass('active'); }); </script> {% endblock %}

#編輯班級數據 @auth def handle_edit_classes(request): if request.method == "GET": nid = request.GET.get('nid') obj = Classes.objects.filter(id=nid).first() return render(request,"edit_classes.html",{'obj':obj}) elif request.method == "POST": nid = request.POST.get('nid') caption = request.POST.get('caption') Classes.objects.filter(id=nid).update(caption=caption) return redirect('/classes') else: return redirect("index")
七、學生管理
相關url
url(r'^student$', handle_student), url(r'^add_student', handle_add_student),
url(r'^edit_student', handle_edit_student),
查詢學生信息及分頁

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>學生列表</h1> <div> <a href="/add_student">添加</a> </div> <table border="1"> <thead> <tr> <th>學生ID</th> <th>學生姓名</th> <th>學生郵箱</th> <th>所屬班級ID</th> <th>所屬班級</th> <th>操作</th> </tr> </thead> <tbody> {% for row in result %} <tr> <td>{{ row.id }}</td> <td>{{ row.name }}</td> <td>{{ row.email }}</td> <td>{{ row.cls.id }}</td> <td>{{ row.cls.caption }}</td> <td> <a>編輯</a> | <a>刪除</a> </td> </tr> {% endfor %} </tbody> </table> <div class="pagination"> {{ str_pager|safe }} </div> {% endblock %} {% block js %} <script> $(function () { $('#menu_student').addClass('active'); }) </script> {% endblock %}

@auth def handle_student(request): if request.method == "GET": # for i in range(1,100): # Student.objects.create(name='root' + str(i), # email='root@live.com' + str(i), # cls_id=i) username = request.session.get("username") # 封裝類的方式實現分頁 from utils.page import PagerHelper current_page = request.GET.get('p', 1) current_page = int(current_page) total_count = Student.objects.all().count() obj = PagerHelper(total_count, current_page, '/student', 10) result = Student.objects.all()[obj.db_start:obj.db_end] pager = obj.pager_str() return render(request,'student.html',{'username':username,'result': result,'str_pager': pager})
添加學生

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>添加學生</h1> <form action="/add_student" method="POST"> <p> <!--placeholder 屬性規定可描述輸入字段預期值的簡短的提示信息,該提示會在用戶輸入值之前顯示在輸入字段中。--> <input placeholder="學生姓名" type="text" name="name" /> </p> <p> <input placeholder="學生郵箱" type="text" name="email" /> </p> <p> <!-- <input placeholder="班級ID" type="text" name="cls_id" /> --> <select name="cls_id"> {% for op in cls_list %} <option value="{{ op.id }}">{{ op.caption }}</option> {% endfor %} </select> </p> <input type="submit" value="提交"/> </form> {% endblock %} {% block js %} <script> $(function () { $('#menu_student').addClass('active'); }); </script> {% endblock %}

@auth def handle_add_student(request): if request.method == "GET": cls_list = Classes.objects.all()[0: 10] #print(cls_list) return render(request,'add_student.html',{'cls_list': cls_list}) elif request.method == "POST": name = request.POST.get('name') email = request.POST.get('email') cls_id = request.POST.get('cls_id') #print(cls_id) Student.objects.create(name=name,email=email,cls_id=cls_id) return redirect('/student')
編輯學生信息

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>學生列表</h1> <div> <a href="/add_student">添加</a> </div> <table border="1"> <thead> <tr> <th>學生ID</th> <th>學生姓名</th> <th>學生郵箱</th> <th>所屬班級ID</th> <th>所屬班級</th> <th>操作</th> </tr> </thead> <tbody> {% for row in result %} <tr> <td>{{ row.id }}</td> <td>{{ row.name }}</td> <td>{{ row.email }}</td> <td>{{ row.cls.id }}</td> <td>{{ row.cls.caption }}</td> <td> <a href="/edit_student?nid={{ row.id }}">編輯</a> | <a>刪除</a> </td> </tr> {% endfor %} </tbody> </table> <div class="pagination"> {{ str_pager|safe }} </div> {% endblock %} {% block js %} <script> $(function () { $('#menu_student').addClass('active'); }) </script> {% endblock %}

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>編輯學生</h1> <form action="/edit_student" method="POST"> <input class="hide" type="text" name="id" value="{{ obj.id }}" /> <p> <input placeholder="學生姓名" type="text" name="name" value="{{ obj.name }}" /> </p> <p> <input placeholder="學生郵箱" type="text" name="email" value="{{ obj.email }}" /> </p> <p> <!-- <input placeholder="班級ID" type="text" name="cls_id" /> --> <select name="cls_id"> {% for op in cls_list %} {% if op.id == obj.cls_id %} <option selected="selected" value="{{ op.id }}">{{ op.caption }}</option> {% else %} <option value="{{ op.id }}">{{ op.caption }}</option> {% endif %} {% endfor %} </select> </p> <input type="submit" value="提交"/> </form> {% endblock %} {% block js %} <script> $(function () { $('#menu_student').addClass('active'); }); </script> {% endblock %}

#編輯學生信息 @auth def handle_edit_student(request): if request.method == "GET": cls_list = Classes.objects.all()[0: 20] nid = request.GET.get('nid') obj = Student.objects.get(id=nid) return render(request, 'edit_student.html', {'cls_list': cls_list, "obj": obj}) elif request.method == "POST": nid = request.POST.get('id') name = request.POST.get('name') email = request.POST.get('email') cls_id = request.POST.get('cls_id') Student.objects.filter(id=nid).update(name=name, email=email, cls_id=cls_id) return redirect('/student')
刪除學生信息

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>學生列表</h1> <div> <a href="/add_student">添加</a> </div> <table border="1"> <thead> <tr> <th>學生ID</th> <th>學生姓名</th> <th>學生郵箱</th> <th>所屬班級ID</th> <th>所屬班級</th> <th>操作</th> </tr> </thead> <tbody> {% for row in result %} <tr> <td>{{ row.id }}</td> <td>{{ row.name }}</td> <td>{{ row.email }}</td> <td>{{ row.cls.id }}</td> <td>{{ row.cls.caption }}</td> <td> <a href="/edit_student?nid={{ row.id }}">編輯</a> | <a href="/dele_student?nid={{ row.id }}">刪除</a> </td> </tr> {% endfor %} </tbody> </table> <div class="pagination"> {{ str_pager|safe }} </div> {% endblock %} {% block js %} <script> $(function () { $('#menu_student').addClass('active'); }) </script> {% endblock %}

#刪除學生信息 @auth def handle_dele_student(request): if request.method == "GET": nid = request.GET.get('nid') #print(nid) Student.objects.filter(id=nid).delete() return redirect('/student') else: return redirect('/student')
八、老師管理
相關url
url(r'^teacher$', handle_teacher), url(r'^add_teacher', handle_add_teacher), url(r'^edit_teacher-(\d+)', handle_edit_teacher),
url(r'^dele_teacher', handle_dele_teacher),
查詢老師信息

{% extends "base.html" %} {% block css %} <style> .tag{ display: inline-block; padding: 5px; border: 1px solid red; background-color: lightpink; cursor: pointer; } </style> {% endblock %} {% block content %} <!--<h1>老師列表</h1>--> <!--<table border="1">--> <!--<thead></thead>--> <!--<tbody>--> <!--{% for obj in teacher_list %}--> <!--<tr>--> <!--<td>{{ obj.id }}</td>--> <!--<td>{{ obj.name }}</td>--> <!--<td>--> <!--{% for c in obj.cls.all %}--> <!--<span class="tag" nid="{{ c.id }}">{{ c.caption }}</span>--> <!--{% endfor %}--> <!--</td>--> <!--</tr>--> <!--{% endfor %}--> <!--</tbody>--> <!--</table>--> <h1>老師列表</h1> <div> <a href="/add_teacher">添加</a> </div> <table border="1"> <thead></thead> <tbody> {% for dic in teacher_list.values %} <tr> <td>{{ dic.nid }}</td> <td>{{ dic.name }}</td> <td> {% for c in dic.cls_list %} <span class="tag" nid="{{ c.id }}">{{ c.caption }}</span> {% endfor %} </td> <td> <a href="/edit_teacher-{{ dic.nid }}">編輯</a> <a href="/dele_teacher?nid={{ dic.nid }}">刪除</a> </td> </tr> {% endfor %} </tbody> </table> {% endblock %} {% block js %} {% endblock %}

#查詢老師信息 @auth def handle_teacher(request): current_user = request.session.get('username') # 方式一:查詢數據庫次數比較多 # teacher_list = Teacher.objects.all() # for i in teacher_list: # print(i.id,i.name,i.cls.all()) #return render(request, 'teacher.html', {'username': current_user, "teacher_list": teacher_list}) #方式二:次方式比較好,數據庫查詢次數少 #teacher_list = Teacher.objects.filter(id__in=Teacher.objects.all()[0:5]).values('id', 'name', 'cls__id', 'cls__caption') teacher_list = Teacher.objects.filter(id__in=Teacher.objects.all()).values('id', 'name', 'cls__id', 'cls__caption') """ #定義字典存放查詢出來信息 result = { 1: { 'nid': 1, 'name': '王老師', 'cls_list':[ {'id': 1, 'caption': "一班"}, {'id': 2, 'caption': "二班"} ] }, 2: { 'nid': 2, 'name': '張老師', 'cls_list': [ {'id': 1, 'caption': "二班"}, {'id': 5, 'caption': "三班"} ] } } #也可以定義類實現,后面完善 # class Node: # def __init__(self,nid,name): # self.nid = nid # self.name = name # self.cls_list = [] """ result = {} for t in teacher_list: #print(t['id'],t['name'],t['cls__id'],t['cls__caption']) if t['id'] in result: if t['cls__id']: result[t['id']]['cls_list'].append({'id': t['cls__id'], 'caption': t['cls__caption']}) else: if t['cls__id']: temp = [{'id': t['cls__id'], 'caption': t['cls__caption']}, ] else: temp = [] result[t['id']] = { 'nid': t['id'], 'name': t['name'], 'cls_list': temp } return render(request, 'teacher.html', {'username': current_user, "teacher_list": result})
添加老師信息

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>添加老師</h1> <form action="/add_teacher" method="POST"> <p> 老師姓名:<input name="name" type="text" /> </p> <p> 班級: <select name="cls" multiple> {% for row in cls_list %} <option value="{{ row.id }}">{{ row.caption }}</option> {% endfor %} </select> </p> <input type="submit" value="提交" /> </form> {% endblock %} {% block js %} <script> $(function () { $('#menu_teacher').addClass('active'); }) </script> {% endblock %}

#添加老師信息 @auth def handle_add_teacher(request): if request.method == "GET": cls_list = Classes.objects.all() #print(cls_list) return render(request,'add_teacher.html',{'cls_list':cls_list}) elif request.method == "POST": name = request.POST.get('name') cls = request.POST.getlist('cls') #['3', '4'] #print(name) #print(cls) #創建老師 obj = Teacher.objects.create(name=name) #創建老師和班級的對應關系 obj.cls.add(*cls) return redirect('/teacher')
編輯老師信息

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>編輯老師</h1> <form action="/edit_teacher-{{ obj.id }}" method="POST"> <input style="display: none" type="text" id="nid" value="{{ obj.id }}" /> <p> 老師姓名:<input name="name" type="text" value="{{ obj.name }}" /> </p> <p> 班級: <select name="cls" multiple> {% for row in cls_list %} {% if row.id in id_list %} <option value="{{ row.id }}" selected="selected">{{ row.caption }}</option> {% else %} <option value="{{ row.id }}">{{ row.caption }}</option> {% endif %} {% endfor %} </select> </p> <input type="submit" value="提交" /> </form> {% endblock %} {% block js %} <script> $(function () { $('#menu_teacher').addClass('active'); }) </script> {% endblock %}

#編輯老師信息 @auth def handle_edit_teacher(request,nid): if request.method == "GET": #獲取當前老師信息 obj = Teacher.objects.get(id=nid) # 獲取當前老師對應的所有班級 <QuerySet [(1,), (3,), (6,)]> #obj_cls_list = obj.cls.all().values_list('id') obj_cls_list=obj.cls.all().values_list() # #print(obj_cls_list) # <QuerySet [(1, '一班'), (3, '三班'), (6, '六班')]> id_list = list(zip(*obj_cls_list))[0] #print(id_list) #(1, 3, 6) #獲取所有的班級 cls_list = Classes.objects.all() return render(request, 'edit_teacher.html', {'obj': obj, "cls_list": cls_list, "id_list": id_list}) elif request.method == "POST": # nid = request.POST.get('nid') name = request.POST.get('name') cls_li = request.POST.getlist('cls') obj = Teacher.objects.get(id=nid) obj.name = name obj.save() #更新對應班級信息,使用set()時,更新對象為多個時,不用在列表前加*,使用set更新時是先清空在添加 obj.cls.set(cls_li) return redirect('/teacher')
刪除老師信息

#刪除老師信息 @auth def handle_dele_teacher(request): if request.method == "GET": nid = request.GET.get('nid') #print(nid) Teacher.objects.filter(id=nid).delete() return redirect('/teacher') else: return redirect('/teacher')
編輯老師信息(左右選擇框實現)

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>編輯老師</h1> <form action="/edit_teacher-{{ obj.id }}" method="POST"> <input style="display: none" type="text" id="nid" value="{{ obj.id }}" /> <p> 老師姓名:<input name="name" type="text" value="{{ obj.name }}" /> </p> <p> 已管理班級 <select id="sel" name="cls" multiple> {% for row in obj_cls_list %} <option value="{{ row.0 }}">{{ row.1 }}</option> {% endfor %} </select> 未管理班級: <select id="none" multiple> {% for row in cls_list %} <option value="{{ row.id }}">{{ row.caption }}</option> {% endfor %} </select> </p> <div> <a id="removeCls"> >> </a> <a id="addCls"> << </a> </div> <input id="submit_form" type="submit" value="提交" /> </form> {% endblock %} {% block js %} <script> $(function () { $('#menu_teacher').addClass('active'); bindRemoveCls(); bindAddCls(); bindSubmitForm(); }) /* jQuery對象和DOM對象相互轉換 DOM --> jQuery :只需用$()把DOM對象包起來即可 jQuery --> DOM:jQuery對象是一個類似數組的對象,可以通過[index]方法得到相應的DOM對象 $('#sel')[0] */ function bindSubmitForm(){ $('#submit_form').click(function () { // 提交到后台前讓select中的全選中 $('#sel').children().each(function () { $(this).prop('selected', true); }) }) } function bindRemoveCls() { $('#removeCls').click(function () { var options = $('#sel')[0].selectedOptions; while(options.length>0){ $(options[0]).appendTo('#none'); } }) } function bindAddCls() { $('#addCls').click(function () { var options = $('#none')[0].selectedOptions; while(options.length>0){ $(options[0]).appendTo('#sel'); } }) } </script> {% endblock %}

#編輯老師信息 方式二:有左右選擇框 def handle_edit_teacher(request,nid): # 獲取當前老師信息 # 獲取當前老師對應的所有班級 # - 獲取所有的班級 # - 獲取當前老師未對應的所有班級 if request.method == "GET": # 當前老師的信息 obj = Teacher.objects.get(id=nid) # 獲取當前老師已經管理的所有班級 # <QuerySet [(2, '二1班'), (3, '三班')]> obj_cls_list = obj.cls.all().values_list('id', 'caption') # 已經管理的班級的ID列表,如果老師沒有管理班級為空列表 id_list = list(zip(*obj_cls_list))[0] if obj_cls_list else [] # # [1,2,3] # 獲取未管理的班級, # cls_list = Classes.objects.filter(id__in=id_list) cls_list = Classes.objects.exclude(id__in=id_list) #print(cls_list[0].id,cls_list[0].caption) 1 一班 return render(request, 'edit_teacher.html', {'obj': obj, 'obj_cls_list': obj_cls_list, "cls_list": cls_list, "id_list": id_list }) elif request.method == "POST": # nid = request.POST.get('nid') name = request.POST.get('name') cls_li = request.POST.getlist('cls') #print(cls_li) obj = Teacher.objects.get(id=nid) obj.name = name obj.save() #使用set()時,更新對象為多個時,不用在列表前加*,使用set更新時是先清空在添加 obj.cls.set(cls_li) return redirect('/teacher')
三級聯動實現
相關url url(r'^menu', menu), url(r'^fetch_city', fetch_city), url(r'^fetch_xian', fetch_xian),

class Province(models.Model): name = models.CharField(max_length=32) class City(models.Model): name = models.CharField(max_length=32) pro = models.ForeignKey("Province",on_delete=models.CASCADE) class Xian(models.Model): name = models.CharField(max_length=32) cy = models.ForeignKey("City",on_delete=models.CASCADE)

def menu(request): pro_list = Province.objects.all() return render(request,'menus.html',{'pro_list':pro_list}) """ 二級聯動 def fetch_city(request): # 根據用戶傳入的省份ID,獲取與其相關的所有市ID # ret = {'status': True, 'error': None, 'data': None} province_id = request.GET.get('province_id') result = City.objects.filter(pro_id=province_id) #print(result) # QuerySet內部放置對象 from django.core import serializers data = serializers.serialize("json", result) #[{"model": "app01.city", "pk": 1, "fields": {"name": "\u6d66\u4e1c", "pro": 1}}, {"model": "app01.city", "pk": 2, "fields": {"name": "\u6d66\u897f", "pro": 1}}] #print(data) return HttpResponse(data) """ #三級聯動 def fetch_city(request): # 根據用戶傳入的省份ID,獲取與其相關的所有市ID # ret = {'status': True, 'error': None, 'data': None} province_id = request.GET.get('province_id') # result = models.City.objects.filter(pro_id=province_id) # # QuerySet內部放置對象 # from django.core import serializers # data = serializers.serialize("json", result) result = City.objects.filter(pro_id=province_id).values('id','name') # QuerySet內部放置對象 result = list(result) data = json.dumps(result) # result = models.City.objects.filter(pro_id=province_id).values_list('id','name') # # QuerySet內部放置對象 # print(result) # result = list(result) # import json # data = json.dumps(result) return HttpResponse(data) def fetch_xian(request): # for i in range(10): # models.Xian.objects.create(name='縣'+ str(i), cy_id=1) city_id = request.GET.get('city_id') xian_list = Xian.objects.filter(cy_id=city_id).values('id','name') xian_list = list(xian_list) return HttpResponse(json.dumps(xian_list))

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>二級聯動</h1> <select id="province"> <option value="-1">請選擇省份</option> {% for p in pro_list %} <option value="{{ p.id }}">{{ p.name }}</option> {% endfor %} </select> <select id="city"> <option value="-1">請選擇市</option> </select> {% endblock %} {% block js %} <script> $(function () { bindProvinceEvent(); bindCityEvent() }); function bindProvinceEvent(){ $('#province').change(function () { /*獲取選中省份的id*/ var v = $(this).val(); if(v == '-1'){ }else{ //獲取option的值方式:例如獲取第一個值 $('#test option:first').val() //清空city中option的值 $('#city option:gt(0)').remove(); $.ajax({ url: '/fetch_city', type: 'GET', data: {'province_id': v}, dataType: 'json', success: function (arg) { $.each(arg, function(k,v){ var city_id = v.pk; var city_name = v.fields.name; var tag = document.createElement('option'); tag.innerHTML = city_name; tag.setAttribute('value', city_id); $('#city').append(tag); }); } }) } }) } </script> {% endblock %}

{% extends "base.html" %} {% block css %} {% endblock %} {% block content %} <h1>三級聯動</h1> <select id="province"> <option value="-1">請選擇省份</option> {% for p in pro_list %} <option value="{{ p.id }}">{{ p.name }}</option> {% endfor %} </select> <select id="city"> <option value="-1">請選擇市</option> </select> <select id="xian"> <option value="-1">請選擇縣</option> </select> {% endblock %} {% block js %} <script> $(function () { bindProvinceEvent(); bindCityEvent() }); function bindCityEvent() { $('#city').change(function () { var v = $(this).val(); if (v == "-1"){ }else{ $('#xian option:gt(0)').remove(); $.ajax({ url: '/fetch_xian', type: 'GET', data: {'city_id': v}, dataType: 'json', success:function (arg) { $.each(arg, function(k,v){ var tag = document.createElement('option'); tag.innerHTML = v.name; tag.setAttribute('value', v.id); $('#xian').append(tag); }); } }) } }) } function bindProvinceEvent(){ $('#province').change(function () { var v = $(this).val(); if(v == '-1'){ }else{ $('#city option:gt(0)').remove(); $('#xian option:gt(0)').remove(); $.ajax({ url: '/fetch_city', type: 'GET', data: {'province_id': v}, dataType: 'json', success: function (arg) { $.each(arg, function(k,v){ var tag = document.createElement('option'); tag.innerHTML = v.name; tag.setAttribute('value', v.id); $('#city').append(tag); }); } }) } }) } </script> {% endblock %}
github地址:https://github.com/quanloveshui/usermanager.git