Python全棧之路-Django(六)

1 Ajax發送數據

發送數據有列表時,須要添加traditional:truecss

$.ajax({
    ...
    data: {'k1':[1,2,3,4]},
    traditional:true,
    ...
})

發送數據有字典時,需JSON序列化成字符串後發送給後端html

$.ajax({
    ...
    data: {'k1':JSON.stringify({'k2':'v2','k3':'v3',...})},
    ...
})

2 Bootstrap

目標:完善學員管理系統
1.Bootstrapmysql

  • 定義:一個包含CSS和JS的一個代碼庫
  • 咱們須要瞭解的是:
    • 樣式
    • 支持響應式佈局 @media (導航條)
    • 柵格 http://v3.bootcss.com/css/#grid

響應式佈局:jquery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .pg-header{
            background-color: #2aabd2;
            height: 48px;
        }
        @media (max-width: 900px) {
            .pg-header{
                background-color: red;
                height: 48px;
            }
        }
        @media (max-width: 700px) {
            .pg-header{
                background-color: green;
                height: 48px;
            }
        }

    </style>
</head>
<body>
    <div class="pg-header"></div>
</body>
</html>

bootstrap導航條ajax

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>
    <nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>
</body>
</html>

3 學員管理後臺佈局

Django母版sql

  • 母版:存放全部頁面公用代碼
  • 子版:繼承母版並填充自定義當前頁面的代碼

urls.pydjango

from django.conf.urls import url
from django.contrib import admin
from app01 import views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^classes/', views.classes),
    url(r'^add_class/', views.add_class),
    url(r'^del_class/', views.del_class),
    url(r'^edit_class/', views.edit_class),
    url(r'^students/', views.students),
    url(r'^add_student/', views.add_student),
    url(r'^del_student/', views.del_student),
    url(r'^edit_student/', views.edit_student),
    url(r'^modal_add_class/', views.modal_add_class),
    url(r'^modal_edit_class/', views.modal_edit_class),
    url(r'^modal_add_student/', views.modal_add_student),
    url(r'^modal_edit_student/', views.modal_edit_student),
    url(r'^teachers/', views.teachers),
    url(r'^add_teacher/', views.add_teacher),
    url(r'^edit_teacher/', views.edit_teacher),
    url(r'^get_all_class/', views.get_all_class),
    url(r'^modal_add_teacher/', views.modal_add_teacher),
    url(r'^test/', views.test),
    url(r'^layout/', views.layout),
    url(r'^login/', views.login),
]

templates.layout.htmlbootstrap

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
    <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.css">
    <link rel="stylesheet" href="/static/css/commons.css">
    {% block css1 %}
    
    {% endblock %}
    <style>

    </style>
</head>
<body>
    <div class="pg-header">
        <div class="logo left">學生後臺管理系統</div>
        <div class="avatar right" style="position: relative;">
            <img style="width: 40px;height: 40px" src="/static/images/tx.png" alt="">
            <div class="user-info hide1">
                <a href="">我的資料</a>
                <a href="">註銷</a>
            </div>
        </div>
        <div class="rmenus right">
            <a href=""><i class="fa fa-commenting-o" aria-hidden="true"></i> 消息</a>
            <a href=""><i class="fa fa-envelope-o" aria-hidden="true"></i> 郵件</a>
        </div>

    </div>
    <div class="pg-body">
        <div class="menus">
            <a href="/classes/">班級管理</a>
            <a href="/students/">學生管理</a>
            <a href="/teachers/">老師管理</a>
        </div>
        <div class="content">
            {% block body1 %}
            
            {% endblock %}
        </div>
    </div>
    {% block body2 %}
    
    {% endblock %}
    
    {% block script1 %}
        
    {% endblock %}
</body>
</html>

templates.classes.html後端

{% extends "layout.html" %}
{% block css1 %}
    <link rel="stylesheet" href="/static/css/classes.css">
{% endblock %}
{% block body1 %}
    <div>
        <ol class="breadcrumb">
          <li><a href="#">首頁</a></li>
{#          <li><a href="#">班級管理</a></li>#}
          <li class="active">班級管理</li>
        </ol>
    </div>
    <div style="width: 1000px;margin: 20px">
        <div style="margin: 10px 0;">
            <a href="/add_class/" class="btn btn-primary">添加班級</a>
            <a href="#" onclick="showModal();" class="btn btn-info">對話框添加</a>
        </div>
        <div>
            <table class="table table-striped table-bordered table-hover">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>班級名稱</th>
                    <th>操做</th>
                </tr>
                </thead>
                <tbody>
                    {% for row in class_list %}
                    <tr>
                        <td>{{ row.id }}</td>
                        <td>{{ row.class_name }}</td>
                        <td>
                            <a href="/del_class/?id={{ row.id }}" class="glyphicon glyphicon-trash">刪除 |</a>
                            <a href="#" onclick="return modalEdit(this);" class="glyphicon glyphicon-pencil">對話框編輯 |</a>
                            <a href="/edit_class/?id={{ row.id }}" class="glyphicon glyphicon-pencil">編輯</a>
                        </td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
        <nav aria-label="Page navigation">
          <ul class="pagination">
            <li>
              <a href="#" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
              </a>
            </li>
            <li><a href="#">1</a></li>
            <li><a href="#">2</a></li>
            <li><a href="#">3</a></li>
            <li><a href="#">4</a></li>
            <li><a href="#">5</a></li>
            <li>
              <a href="#" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
              </a>
            </li>
          </ul>
        </nav>
    </div>

{% endblock %}

{% block body2 %}
<div id="shadow" class="hide"></div>
<div id="modal" class="hide">
    <form action="/modal_add_class/" method="post">
        <p><input type="text" name="class_name" id="class_name"></p>
        <input type="button" value="提交" onclick="AjaxSend();">
        <input type="button" value="取消" onclick="cancleModal();">
        <span id="errormsg"></span>
    </form>
</div>
<div id="editModal" class="hide">
    <h3>編輯框</h3>
    <form action="/modal_add_class/" method="post">
        <p><input type="text" name="class_name" id="edit_class_name"></p>
        <p><input type="text" name="class_id" style="display: none" id="edit_class_id"></p>
        <input type="button" value="提交" onclick="editAjaxSend();">
        <input type="button" value="取消" onclick="cancleModal();">
        <span id="errormsg"></span>
    </form>
</div>
{% endblock %}

{% block script1 %}
<script src="/static/jquery-3.2.1.min.js"></script>
<script>
    function showModal(){
        document.getElementById('shadow').classList.remove('hide');
        document.getElementById('modal').classList.remove('hide');
    }

    function cancleModal() {
        document.getElementById('shadow').classList.add('hide');
        document.getElementById('modal').classList.add('hide');
        document.getElementById('editModal').classList.add('hide');
    }

    function AjaxSend() {
        $.ajax({
            url: '/modal_add_class/', // 提交地址
            type: 'POST',             // 提交方式
            data: {'class_name': $('#class_name').val()},  // 提交數據
            success: function (data) { // 當服務端處理完成後,返回數據時,該函數自動調用
                // data 爲返回的數據
                if(data == 'ok'){
{#                        location.href='/classes/';#}
                    location.reload();
                }else{
                    $('#errormsg').text(data);
                }
            }
        })
    }

    function modalEdit(self) {
        document.getElementById('shadow').classList.remove('hide');
        document.getElementById('editModal').classList.remove('hide');
        /*
        1.獲取當前標籤
        2.當前標籤父標籤的上方的標籤
        3.獲取當前行班級名,放入編輯框
         */
        var row = $(self).parent().prevAll();
        var content = $(row[0]).text();
        $('#edit_class_name').val(content);
        var class_id=$(row[1]).text();
        $('#edit_class_id').val(class_id)
    }

    function editAjaxSend() {
        var class_id = $('#edit_class_id').val();
        var class_name = $('#edit_class_name').val();

        $.ajax({
            url:'/modal_edit_class/',
            type:'POST',
            data: {'class_id':class_id,'class_name':class_name},
            success:function (arg) {
                // arg 是字符串類型
                // JSON.parse(字符串) => 對象
                // JSON.stringify(對象) => 字符串
                arg = JSON.parse(arg);
                if(arg.status){
                    location.reload();
                }else{
                    alert(arg.message);
                }
            }
        })
    }
</script>
{% endblock %}

templates.teachers.html瀏覽器

{% extends "layout.html" %}
{% block css1 %}
    <style>
        .shadow{
            position: fixed;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            background-color: black;
            opacity: 0.3;
            z-index: 999;
        }
        .add_modal,.edit_modal{
            position: fixed;
            top: 50%;
            left: 50%;
            width: 400px;
            height: 300px;
            margin-top: -150px;
            margin-left: -200px;
            z-index: 1000;
            background-color: white;
        }
        .hide{
            display: none;
        }
        .loading{
            position: fixed;
            width: 32px;
            height: 32px;
            left: 50%;
            top:50%;
            margin-left: -16px;
            margin-top: -16px;
            background-image: url("/static/images/loading.gif");
        }
</style>
{% endblock %}

{% block body1 %}
    <div>
        <ol class="breadcrumb">
          <li><a href="#">首頁</a></li>
{#          <li><a href="#">老師管理</a></li>#}
          <li class="active">老師管理</li>
        </ol>
    </div>
    <div style="width: 1200px;margin: 20px">
        <div style="margin-bottom: 20px">
            <a href="/add_teacher/" class="btn btn-primary">添加老師</a>
            <a href="#" id="btnAdd" class="btn btn-info">對話框添加</a>
        </div>
        <div>
            <table class="table table-striped table-bordered table-hover">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>老師姓名</th>
                    <th>任教班級</th>
                    <th>操做</th>
                </tr>
                </thead>
                <tbody>
                    {% for row in teacher_list %}
                    <tr>
                        <td>{{ row.teacher_id }}</td>
                        <td>{{ row.teacher_name }}</td>
                        <td>
                            {% for item in  row.class_name %}
                                <span style="display: inline-block;margin-right: 10px;">{{ item }}</span>
                            {% endfor %}
                        </td>
                        <td>
                            <a href="/edit_teacher/?teacher_id={{ row.teacher_id }}">編輯</a>
                            <a>刪除</a>
                        </td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    <nav aria-label="Page navigation">
          <ul class="pagination">
            <li>
              <a href="#" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
              </a>
            </li>
            <li><a href="#">1</a></li>
            <li><a href="#">2</a></li>
            <li><a href="#">3</a></li>
            <li><a href="#">4</a></li>
            <li><a href="#">5</a></li>
            <li>
              <a href="#" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
              </a>
            </li>
          </ul>
        </nav>
    </div>
{% endblock %}

{% block body2 %}
    <div class="shadow hide"></div>
    <div class="add_modal hide">
        <p>
            <input id="addTeacherName" type="text" name="teacher_name" placeholder="老師姓名">
        </p>
        <p>任教班級
            <select multiple size="10" id="addClassIds" name="class_id">

            </select>
        </p>
        <input id="btnAddTeacher" type="button" value="添加">
        <input id="btnCancelModal" type="button" value="取消">
        <span id="addErrorMsg"></span>

    </div>
    <div id="loading" class="loading hide"></div>
{% endblock %}

{% block script1 %}
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script>
        $(function () {
            bindAdd();
            bindBtnAddTeacher();
        });
        function bindAdd() {
            $('#btnAdd').click(function () {
                $('#loading').removeClass('hide');
                /*
                發送ajax請求,獲取全部班級信息
                在班級列表下拉框中生成option
                 */
                $.ajax({
                    url: '/get_all_class/',
                    type: 'POST',
                    dataType: 'JSON',
                    success:function (arg) {
                        // 將全部的數據添加到select option框
                        $.each(arg,function (i,row) {
                            $('.shadow,.add_modal').removeClass('hide')
                            var tag = document.createElement('option');
                            tag.innerHTML = row.class_name;
                            tag.setAttribute('value',row.class_id);
                            $('#addClassIds').append(tag);
                        })
                    }
                })

            });

            $('#btnCancelModal').click(function () {
                $('.shadow,.add_modal').addClass('hide')


            })
        }

        function bindBtnAddTeacher() {
            $('#btnAddTeacher').click(function () {
                var teacher_name = $('#addTeacherName').val();
                var class_id_list = $('#addClassIds').val();
                console.log(teacher_name, class_id_list);
                $.ajax({
                    url:'/modal_add_teacher/',
                    type: 'POST',
                    data: {'teacher_name': teacher_name,'class_id_list':class_id_list},
                    traditional:true,  // 若是提交的數據的值有列表,則須要添加此屬性
                    dataType: 'JSON',
                    success:function (arg) {
                        if(arg.status){
                            location.reload();
                        }else{
{#                            $('#addErrorMsg').innerText = arg.message;#}
                            alert(arg.message)
                        }
                    }

                })
            })
        }
    </script>
{% endblock %}


static.css.classes.css
.hide{
    display: none;
}
#shadow{
    position: fixed;
    left:0;
    top:0;
    right: 0;
    bottom: 0;
    background-color: black;
    opacity: 0.4;
    z-index: 999;
}
#modal,#editModal{
    z-index: 1000;
    position: fixed;
    left: 50%;
    top: 50%;
    height: 300px;
    width: 400px;
    background-color: white;
    margin-left: -200px;
    margin-top: -150px;
}

static.css.commons.css
body{
    margin: 0;
}
.left{
    float: left;
}
.right{
    float: right;
}
.pg-header{
    height: 48px;
    min-width: 1190px;
    line-height: 48px;
    background-color: #2aabd2;
}
.menus{
    width: 200px;
    position: absolute;
    left: 0;
    bottom: 0;
    top: 48px;
    border-right: 1px solid #dddddd;
    background-color: #dddddd;

}
.content{
    position: absolute;
    left: 200px;
    right: 0;
    top: 48px;
    bottom: 0;
    min-width: 990px;
    overflow: scroll;
    z-index: 99;
}
.pg-header .logo{
    color: white;
    font-size: large;
    width: 200px;
    text-align: center;
    border-right: 1px solid red;
}

.pg-header .rmenus a{
    display: inline-block;

    padding: 0 15px;
    color: white;
}
.pg-header .rmenus a:hover{
    background-color: gold;
}
.pg-header .avatar{
    padding: 0 20px;
}
.pg-header .avatar img{
    border-radius: 50%;
}
.pg-header .avatar .user-info {
    width:120px;
    position: absolute;
    top: 48px;
    right: 2px;
    background-color: white;
    z-index: 100;
    border: 1px solid #dddddd;
}
.pg-header .avatar .user-info a{
    display: block;
    text-align: center;
}
.hide1{
    display: none;
}
.pg-header .avatar:hover .user-info{
    display: block;
}

.pg-body .menus a{
    display: block;
    padding: 10px 5px;
    border-bottom: solid 1px white;
    text-align: center;
}
  • Cookie是保存在用戶瀏覽器端的鍵值對
  • 服務端能夠向用戶瀏覽器端寫cookie
  • 客戶端每次發起請求時,會攜帶cookie去

cookie用途:

  • 用戶登陸,保持用戶登陸狀態
  • 投票系統(cookie禁用可破解)

app01.views.py

def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    elif request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'alex' and password == '123':
            obj = redirect('/classes/')
            # obj.set_cookie('ticket','dhffjalih',max_age=10)
            # set_cookie參數:
            # 第一個參數 key
            # 第二個參數 value
            # max_age:超時時間,單位秒
            # path:生效的路徑 默認爲 / 全局生效
            # domain:生效的域名  默認爲當前域名 作單點登陸時會用到
            #
            # 設置加密cookie
            obj.set_signed_cookie('ticket','dhffjalih',salt='abc')
            return obj
        else:
            return render(request, 'login.html')

def classes(request):
    # 去請求的cookie中找憑證
    # tk = request.COOKIES.get('ticket')
    # 獲取加密cookie
    tk = request.get_signed_cookie('ticket',salt='abc')
    if not tk:
        return redirect('/login/')
    conn = pymysql.connect(
        host='localhost',
        port=3306,
        user='root',
        passwd='123456',
        db='db03',
        charset='utf8'
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute(
        'select id,class_name from class order by id;'
    )
    class_list = cursor.fetchall()
    cursor.close()
    conn.close()
    return render(request, 'classes.html', {'class_list': class_list})

PS:能夠用裝飾器完成全部函數的認證登陸功能

相關文章
相關標籤/搜索