Django小項目練習之后台管理系統


    通過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)
models.py
生成同步數據庫的腳本
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
]
urls.py

    登錄頁面/首頁頁面/視圖函數

<!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>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>hell {{ user }}</p>
</body>
</html>
index.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')
views.py

     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雖然在一定程度上解決了“保持狀態”的需求,但是由於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()
session知識

    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")
    
數據庫Session

     通過裝飾器實現判斷用戶是否登錄

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)
View Code

    編寫簡單的班級、學生、老師頁面

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

</body>
</html>
classes.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

         <h1>當前登錄用戶:{{ username }}</h1>

</body>
</html>
student.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

  <h1>當前登錄用戶:{{ username }}</h1>

</body>
</html>
teacher.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')
views.py

 四、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>
base.html
{% extends "base.html" %}

{% block css %}

{% endblock %}

{% block content %}
老師列表
{% endblock %}


{% block js %}

{% endblock %}
teacher.html
{% extends "base.html" %}
{% block css %}
{% endblock %}

{% block content %}
學生列表
{% endblock %}

{% block js %}

{% endblock %}
student.html
{% extends "base.html" %}
{% block css %}
{% endblock %}

{% block content %}
班級列表
{% endblock %}

{% block js %}

{% endblock %}
classes.html

六、班級管理

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>
base.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 %}
classes.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
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')
views.py

 

 

 

 

     通過跳轉到一個新的添加頁面添加信息

---------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 %}
add_classes.html
#處理通過新的頁面添加班級信息提交過來的數據
@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")
views.py

 

 

     分頁實現

@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))
views.py
 .pageactive{
            background-color: #2e6ab1;
            border: 1px solid #000080;
            color: #fff;
            font-weight: bold;
            margin: 0 1px;
            padding: 1px 1px;
        }
新增css

     分頁功能優化(封裝類的方式實現)

"""
    類的方式實現分類
    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
utils/page.py
@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
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 %}
classes.html
{% 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 %}
edit_classes.html
#編輯班級數據
@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")
views.py

 

 

七、學生管理

    相關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 %}
student.html
@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})
views.py

 

    添加學生

{% 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 %}
add_student.html
@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')
views.py

    編輯學生信息

{% 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 %}
student.html
{% 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 %}
edit_student.html
#編輯學生信息
@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')
views.py

     刪除學生信息

{% 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 %}
student.html
#刪除學生信息
@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')
views.py

 八、老師管理

    相關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 %}
teacher.html
#查詢老師信息
@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})
views.py

 

     添加老師信息

{% 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 %}
add_teacher.html
#添加老師信息
@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')
views.py

   

 

 

    編輯老師信息

{% 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 %}
edit_teacher.html
#編輯老師信息
@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')
views.py

     刪除老師信息

#刪除老師信息
@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')
views.py

  編輯老師信息(左右選擇框實現)

{% 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 %}
edit_teacher.html
#編輯老師信息 方式二:有左右選擇框
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')
views.py

 

 三級聯動實現

相關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)
models.py
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))
views.py
{% 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 %}
menus-二級聯動.html
{% 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 %}
menus.html

 

 

 

github地址:https://github.com/quanloveshui/usermanager.git


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM