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

posted @ 2019-10-16 14:17  泉love水  阅读(2105)  评论(0编辑  收藏  举报