會議室預訂系統(meeting room booking system)

1、目標及業務流程

指望效果:javascript

業務流程:css

  1. 用戶登陸
  2. 預約會議室
  3. 退訂會議室
  4. 選擇日期;今日以及之後日期

2、表結構設計和生成

一、models.py(用戶繼承AbstractUser)

from django.db import models
# Create your models here.
from django.db import models
from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    """用戶信息表"""
    tel = models.CharField(max_length=32)

class Room(models.Model):
    """會議室表"""
    caption = models.CharField(max_length=32)   # 會議室名字
    num = models.IntegerField()   # 會議室容納人數
    def __str__(self):
        return self.caption

class Book(models.Model):
    """會議室預訂信息"""
    user = models.ForeignKey("UserInfo", on_delete=models.CASCADE)   # CASCADE級聯刪除
    room = models.ForeignKey("Room", on_delete=models.CASCADE)
    date = models.DateField()  # 日期
    time_choices = (    # 時段
        (1, '8:00'),
        (2, '9:00'),
        (3, '10:00'),
        (4, '11:00'),
        (5, '12:00'),
        (6, '13:00'),
        (7, '14:00'),
        (8, '15:00'),
        (9, '16:00'),
        (10, '17:00'),
        (11, '18:00'),
        (12, '19:00'),
        (13, '20:00'),
    )
    time_id = models.IntegerField(choices=time_choices)    # 存數字,choices參數
    class Meta:
        unique_together = (   # 三個聯合惟一,防止有人重複預約
            ('room', 'date', 'time_id'),
        )
    def __str__(self):
        return str(self.user) + "預約了" + str(self.room)

注意:html

(1)Django中提供了AbstractUser類,能夠用來自由定製須要的model

from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    """用戶信息表"""
    tel = models.CharField(max_length=32)

  如上所示,便可在Django的基礎上添加咱們所須要的信息。前端

(2)設置model的時候,設置三個字段聯合惟一

class Book(models.Model):
    """會議室預訂信息"""
    ....
    class Meta:
        unique_together = (   # 三個聯合惟一,防止有人重複預約
            ('room', 'date', 'time_id'),
        )

   存的是key 顯示的是value,且只能存keyjava

二、修改配置文件settings.py,覆蓋默認的User模型

  Django容許你經過修改setting.py文件中的 AUTH_USER_MODEL 設置覆蓋默認的User模型,其值引用一個自定義的模型。python

AUTH_USER_MODEL = "app01.UserInfo"

  上面的值表示Django應用的名稱(必須位於INSTALLLED_APPS中)和你想使用的User模型的名稱。jquery

注意:在建立任何遷移或者第一次運行 manager.py migrate 前設置 AUTH_USER_MODELajax

  設置AUTH_USER_MODEL數據庫結構有很大的影響。改變了一些會使用到的表格,而且會影響到一些外鍵和多對多關係的構造。在你有表格被建立後更改此設置是不被 makemigrations 支持的,而且會致使你須要手動修改數據庫結構,從舊用戶表中導出數據,可能從新應用一些遷移。數據庫

三、數據遷移及建立超級用戶

$ python3 manage.py makemigrations
$ python3 manage.py migrate

  這裏遇到了一個問題:建立項目時沒有建立應用,手動經過manage.py startapp user建立子項目,修改AUTH_USER_MODEL後執行makemigrations一直報錯,找不到app01。django

  建立兩個超級用戶:

MacBook-Pro:MRBS hqs$ python3 manage.py createsuperuser
Username: yuan
Password:yuan1234

MacBook-Pro:MRBS hqs$ python3 manage.py createsuperuser
Username: alex
Password:alex1234

3、系統登陸login

urls.py:

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('book/', views.book),
]

簡單login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    用戶名:<input type="text" name="user">
    密碼:<input type="password" name="pwd">
    <input type="submit">
</form>
</body>
</html>

login視圖函數:

from django.shortcuts import render, redirect
# Create your views here.
from django.contrib import auth

def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        user = auth.authenticate(username=user, password=pwd)
        if user:
            # 登陸成功
            auth.login(request, user)   # 註冊request.user,能夠拿到登陸用戶對象全部信息
            redirect("/index/")

    return render(request, "login.html")

  注意:auth模塊的authenticate()方法,提供了用戶認證,若是認證信息有效,會返回一個  User  對象;若是認證失敗,則返回None。

4、index部分

一、引入admin組件(後臺數據管理組件)並完成admin註冊

admin.py:

from django.contrib import admin
# Register your models here.
from app01.models import *

admin.site.register(UserInfo)
admin.site.register(Book)
admin.site.register(Room)

二、在數據庫添加數據

  

  

三、index視圖函數數據處理和index.html模板渲染

def index(request):
    # 取當前日期
    date = datetime.datetime.now().date()
    print(date)  # 2018-08-17
    # 取預定日期,沒有指定取當前日期
    book_date = request.GET.get("book_date", date)
    print(book_date)  # 2018-08-17

    # 拿到預約表中的時段
    time_choices = Book.time_choices
    # 拿到全部的會議室
    room_list = Room.objects.all()
    # 拿到預約信息
    book_list = Book.objects.filter(date=book_date)

    # 構建標籤
    htmls = ""
    for room in room_list:   # 有多少會議室生成多少行,
        # 每行僅生成了第一列。還有其餘td標籤須要添加,所以此處沒有閉合tr
        htmls += "<tr><td>{}({})</td>".format(room.caption, room.num)

        for time_choice in time_choices:   # 有多少時段就生成多少列

            flag = False   # False表明沒有預約,True表明已經預約
            for book in book_list:    # 循環肯定單元格是否被預約
                if book.room.pk == room.pk and book.time_id == time_choice[0]:
                    # 符合條件說明當前時段會議室已經被預約
                    flag = True
                    break
            print(book)   # 這個book是預約信息
            if flag:
                # 已經被預約,添加class='active'
                if request.user.pk == book.user.pk:
                    # 當前登陸人查看本身的預定信息
                    htmls += "<td class='active' room_id={} time_id={}>{}</td>".format(room.pk, time_choice[0],
                                                                                       book.user.username)
                else:
                    # 非當前登陸人本身的預定信息
                    htmls += "<td class='another_active' room_id={} time_id={}>{}</td>".format(room.pk, time_choice[0],
                                                                                       book.user.username)
            else:
                htmls += "<td room_id={} time_id={}></td>".format(room.pk, time_choice[0])

        # 循環完成後閉合tr標籤
        htmls += "</tr>"

    return render(request, "index.html", locals())
index視圖函數
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
    <script src="/static/js/jquery-1.12.4.min.js"></script>
    <script src="/static/datetimepicker/bootstrap-datetimepicker.min.js"></script>
    <script src="/static/datetimepicker/bootstrap-datetimepicker.zh-CN.js"></script>
    <style>
        .active {
            background-color: green!important;
            color: white;
        }
        .another_active {
            background-color: #0f5687;
            color: white;
        }
    </style>
</head>
<body>
<H3>會議室預約</H3>
<table class="table table-bordered table-striped">
    <thead>
        <tr>
            <th>會議室時間</th>
            {% for time_choice in time_choices %}
                {# 在元組中取第二個值 #}
                <th>{{ time_choice.1 }}</th>
            {% endfor %}
        </tr>
    </thead>
    <tbody>
        {# 因爲模板語法功能不夠強大,所以數據處理仍是放在後臺,在這裏渲染後臺傳遞來的標籤字符串 #}
        {{ htmls|safe }}
    </tbody>
</table>
</html>
index.html

注意:

(1)數據處理仍是在後臺更加方便,前臺渲染後臺傳遞來的標籤字符串

<table class="table table-bordered table-striped">
    <thead>
        <tr>
            <th>會議室時間</th>
            {% for time_choice in time_choices %}
                {# 在元組中取第二個值 #}
                <th>{{ time_choice.1 }}</th>
            {% endfor %}
        </tr>
    </thead>
    <tbody>
        {# 因爲模板語法功能不夠強大,所以數據處理仍是放在後臺,在這裏渲染後臺傳遞來的標籤字符串 #}
        {{ htmls|safe }}
    </tbody>
</table>

  因爲模板語法功能不夠強大,所以數據處理仍是放在後臺,在這裏渲染後臺傳遞來的標籤字符串。

(2)視圖函數字符串處理,運用format格式化函數

def index(request):
    # 拿到預約表中的時間段
    time_choices = Book.time_choices
    # 拿到全部的會議室
    room_list = Room.objects.all()
    # 構建標籤
    htmls = ""
    for room in room_list:
        # 第一列td完成後,還有其餘td標籤須要添加,所以此處沒有閉合tr
        htmls += "<tr><td>{}({})</td>".format(room.caption, room.num)

    return render(request, "index.html", locals())

顯示效果:

  這是Python2.6後新增了一種格式化字符串的函數 str.format(),它加強了字符串格式化的功能。基本語法是經過 {} 和 : 來代替之前的 % 。format 函數能夠接受不限個參數,位置能夠不按順序。

>>>"{} {}".format("hello", "world")    # 不設置指定位置,按默認順序
'hello world'
 
>>> "{0} {1}".format("hello", "world")  # 設置指定位置
'hello world'
 
>>> "{1} {0} {1}".format("hello", "world")  # 設置指定位置
'world hello world'

  還能夠設置參數:

print("網站名:{name}, 地址 {url}".format(name="菜鳥教程", url="www.runoob.com"))
 
# 經過字典設置參數
site = {"name": "菜鳥教程", "url": "www.runoob.com"}
print("網站名:{name}, 地址 {url}".format(**site))
 
# 經過列表索引設置參數
my_list = ['菜鳥教程', 'www.runoob.com']
print("網站名:{0[0]}, 地址 {0[1]}".format(my_list))  # "0" 是必須的

(3)循環會議室生成行,循環時段生成列,標籤字符串拼接處理

def index(request):
    # 拿到預約表中的時間段
    time_choices = Book.time_choices
    # 拿到全部的會議室
    room_list = Room.objects.all()

    # 構建標籤
    htmls = ""
    for room in room_list:   # 有多少會議室生成多少行,
        # 每行僅生成了第一列。還有其餘td標籤須要添加,所以此處沒有閉合tr
        htmls += "<tr><td>{}({})</td>".format(room.caption, room.num)

        for time_choice in time_choices:   # 有多少時段就生成多少列
            # 一次循環就是一個td標籤
            htmls += "<td></td>"

        # 循環完成後閉合tr標籤
        htmls += "</tr>"
    return render(request, "index.html", locals())

  好比會議室有3個,循環會議室生成三行,且拿到會議室名稱和人數限制生成首列;再循環時段,這裏有13個時段,所以生成13列,13個td標籤依次添加進一個tr中,顯示效果以下:

  

(4)給td標籤添加room_id和time_id屬性

for time_choice in time_choices:   # 有多少時段就生成多少列
    # 一次循環就是一個td標籤
    htmls += "<td room_id={} time_id={}></td>".format(room.pk, time_choice[0])

  這樣點擊單元格可肯定點擊的是哪一個會議室哪個時段的單元格,效果以下所示:

  

(5)獲取預定日期信息

import datetime

def index(request):
    # 取當前日期
    date = datetime.datetime.now().date()
    print(date)  # 2018-08-17
    # 取預定日期,沒有指定取當前日期
    book_date = request.GET.get("book_date", date)
    print(book_date)  # 2018-08-17

  index頁面訪問中,若是沒有指定日期,默認顯示的就是當前日的預約信息。

  所以在循環生成表格時,能夠循環肯定單元格是否被預約,已經被預約的添加class=‘active’屬性。

# 構建標籤
htmls = ""
for room in room_list:   # 有多少會議室生成多少行,
    # 每行僅生成了第一列。還有其餘td標籤須要添加,所以此處沒有閉合tr
    htmls += "<tr><td>{}({})</td>".format(room.caption, room.num)

    for time_choice in time_choices:   # 有多少時段就生成多少列

        flag = False   # False表明沒有預約,True表明已經預約
        for book in book_list:    # 循環肯定單元格是否被預約
            if book.room.pk == room.pk and book.time_id == time_choice[0]:
                # 符合條件說明當前時段會議室已經被預約
                flag = True
                break
        if flag:
            # 已經被預約,添加class='active'
            htmls += "<td class='active' room_id={} time_id={}></td>".format(room.pk, time_choice[0])
        else:
            htmls += "<td room_id={} time_id={}></td>".format(room.pk, time_choice[0])

    # 循環完成後閉合tr標籤
    htmls += "</tr>"

(6)在預約單元格添加預約人姓名,並根據登陸人判斷顯示單元格

if flag:
    # 已經被預約,添加class='active'
    if request.user.pk == book.user.pk:
        # 當前登陸人查看本身的預定信息
        htmls += "<td class='active' room_id={} time_id={}>{}</td>".format(room.pk, time_choice[0],
                                                                           book.user.username)
    else:
        # 非當前登陸人本身的預定信息
        htmls += "<td class='another_active' room_id={} time_id={}>{}</td>".format(room.pk, time_choice[0],
                                                                           book.user.username)
else:
    htmls += "<td room_id={} time_id={}></td>".format(room.pk, time_choice[0])

在index中添加樣式:

<style>
    .active {
        background-color: green!important;
        color: white;
    }
    .another_active {
        background-color: #0f5687;
        color: white;
    }
</style>

顯示效果以下:

  

5、前端部分數據處理(index.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
    <script src="/static/js/jquery-1.12.4.min.js"></script>
    <script src="/static/datetimepicker/bootstrap-datetimepicker.min.js"></script>
    <script src="/static/datetimepicker/bootstrap-datetimepicker.zh-CN.js"></script>
    <style>
        .active {
            background-color: green!important;
            color: white;
        }
        .another_active {
            background-color: #0f5687;
            color: white;
        }
        .td_active {
            background-color: lightblue;
            color: white;
        }
    </style>
</head>
<body>
<H3>會議室預約</H3>

<div class="calender pull-right">
    <div class='input-group' style="width: 230px;">
        <input type='text' class="form-control" id='datetimepicker11' placeholder="請選擇日期"/>
        <span class="input-group-addon">
            <span class="glyphicon glyphicon-calendar"></span>
        </span>
    </div>
</div>

<table class="table table-bordered table-striped">
    <thead>
        <tr>
            <th>會議室時間</th>
            {% for time_choice in time_choices %}
                {# 在元組中取第二個值 #}
                <th>{{ time_choice.1 }}</th>
            {% endfor %}
        </tr>
    </thead>
    <tbody>
        {# 因爲模板語法功能不夠強大,所以數據處理仍是放在後臺,在這裏渲染後臺傳遞來的標籤字符串 #}
        {{ htmls|safe }}
    </tbody>
</table>
<button class="btn btn-success pull-right keep">保存</button>

<script>
    // 日期格式化方法
    Date.prototype.yuan = function (fmt) { //author: meizz
        var o = {
            "M+": this.getMonth() + 1, //月份
            "d+": this.getDate(), //日
            "h+": this.getHours(), //小時
            "m+": this.getMinutes(), //分
            "s+": this.getSeconds(), //秒
            "q+": Math.floor((this.getMonth() + 3) / 3), //季度
            "S": this.getMilliseconds() //毫秒
        };
        if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
        for (var k in o)
            if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
        return fmt;
    };

    // room_id 爲鍵,time_id 爲值  {1:[4,5],2:[4,] }   {3:[9,10]}
    var POST_DATA = {
        "ADD":{},
        "DEL":{}
    };

    // 爲td綁定單擊事件
    function BindTd() {
        $('.item').click(function () {
            var room_id = $(this).attr("room_id");
            var time_id = $(this).attr("time_id");

            // 取消預約
            if ($(this).hasClass("active")){
                // 若是點擊的標籤具備active類,直接刪除active類並清空內容
                $(this).removeClass("active").empty();

                if (POST_DATA.DEL[room_id]){
                    // 在數據中已經存有會議室信息,將新單元格time_id添加進數組
                    POST_DATA.DEL[room_id].push(time_id);
                } else {
                    // 在數據中沒有存過對應會議室記錄,直接將time_id對其賦值建立一個字典
                    POST_DATA.DEL[room_id] = [time_id, ];
                }
            }
            // 取消臨時預約
            else if ($(this).hasClass("td_active")) {
                $(this).removeClass("td_active");
                // 點擊刪除臨時預約時添加的數據
                // POST_DATA.ADD[room_id].pop(); // 這個是刪除最後一個元素不對
                POST_DATA.ADD[room_id].splice(POST_DATA.ADD[room_id].indexOf(time_id),1)
            }
            else {
                // 添加預約(空白單元格)
                $(this).addClass("td_active");

                if (POST_DATA.ADD[room_id]){
                    // 在數據中已經存有會議室信息,將新單元格time_id添加進數組
                    POST_DATA.ADD[room_id].push(time_id);
                } else {
                    // 在數據中沒有存過對應會議室記錄,直接將time_id對其賦值建立一個字典
                    POST_DATA.ADD[room_id] = [time_id, ];
                }
            }
        })
    }
    BindTd();
    
    // 日期
    if (location.search.slice(11)){
        CHOOSE_DATE = location.search.slice(11)
    }
    else {
        CHOOSE_DATE = new Date().yuan('yyyy-MM-dd');
    }

    // 發送ajax
    $(".keep").click(function () {
        $.ajax({
            url:"/book/",
            type:"POST",
            data:{
                csrfmiddlewaretoken: '{{ csrf_token }}',
                choose_date:CHOOSE_DATE,
                post_data:JSON.stringify(POST_DATA)
            },
            dataType:"json",
            success:function (data) {
                console.log(data);

                if(data.state){
                    // 預約成功
                    location.href=""
                }else {
                    alert("預約的房間已經被預約");
                    location.href=""
                }
            }
        })
    });

    // 日曆插件
    $('#datetimepicker11').datetimepicker({
        minView: "month",
        language: "zh-CN",
        sideBySide: true,
        format: 'yyyy-mm-dd',
        startDate: new Date(),
        bootcssVer: 3,
        autoclose: true
    }).on('changeDate', book_query);

    function book_query(e) {
        CHOOSE_DATE=e.date.yuan("yyyy-MM-dd");
        location.href="/index/?book_date="+CHOOSE_DATE;
    }
</script>

</html>

一、點擊事件預約和取消——組織數據

<script>
    // room_id 爲鍵,time_id 爲值  {1:[4,5],2:[4,] }   {3:[9,10]}
    var POST_DATA = {
        "ADD":{},
        "DEL":{}
    };

    // 爲td綁定單擊事件
    function BindTd() {
        $('.item').click(function () {
            var room_id = $(this).attr("room_id");
            var time_id = $(this).attr("time_id");

            // 取消預約
            if ($(this).hasClass("active")){
                // 若是點擊的標籤具備active類,直接刪除active類並清空內容
                $(this).removeClass("active").empty();

                if (POST_DATA.DEL[room_id]){
                    // 在數據中已經存有會議室信息,將新單元格time_id添加進數組
                    POST_DATA.DEL[room_id].push(time_id);
                } else {
                    // 在數據中沒有存過對應會議室記錄,直接將time_id對其賦值建立一個字典
                    POST_DATA.DEL[room_id] = [time_id, ];
                }
            }
            // 取消臨時預約
            else if ($(this).hasClass("td_active")) {
                $(this).removeClass("td_active");
                // 點擊刪除臨時預約時添加的數據
                // POST_DATA.ADD[room_id].pop(); // 這個是刪除最後一個元素不對
                POST_DATA.ADD[room_id].splice(POST_DATA.ADD[room_id].indexOf(time_id),1)
            }
            else {
                // 添加預約(空白單元格)
                $(this).addClass("td_active");

                if (POST_DATA.ADD[room_id]){
                    // 在數據中已經存有會議室信息,將新單元格time_id添加進數組
                    POST_DATA.ADD[room_id].push(time_id);
                } else {
                    // 在數據中沒有存過對應會議室記錄,直接將time_id對其賦值建立一個字典
                    POST_DATA.ADD[room_id] = [time_id, ];
                }
            }
        })
    }
    BindTd();
</script>

注意:

(1)取消預約事件

<script>
    // 爲td綁定單擊事件
    function BindTd() {
        $('.item').click(function () {
            // alert($(this).attr("room_id"));   // 點擊顯示會議室id

            // 取消預約
            if ($(this).hasClass("active")){
                // 若是點擊的標籤具備active類,直接刪除active類並清空內容
                $(this).removeClass("active").empty();
            }
            else if ($(this).hasClass("td_active")) {
                $(this).removeClass("td_active");
            }
            else {
                // 空白局域點擊
                $(this).addClass("td_active");
            }
        })
    }
    BindTd();
</script>

  在此次只處理了具備active類和td_active類的狀況,但沒有處理another_active類的狀況,由於這種須要判斷的狀況,必定要交給後端,不然就是前端一套後端一套,點擊保存按鈕發送的js,客戶能夠假裝一個data發送給服務器,若是不作聯合惟一,徹底交給前端會形成很嚴重的安全問題。

(2)數據組織和添加預約

  建立以下所示用js字面量方式建立對象POST_DATA,有兩個屬性(對象)ADD和DEL,這兩個對象的值以room_id爲鍵,以time_id爲值:

<script>
    // room_id 爲鍵,time_id 爲值  {1:[4,5],2:[4,] }   {3:[9,10]}
    var POST_DATA = {
        "ADD":{},
        "DEL":{}
    };
</script>

  在空白單元格點擊,獲取添加數據到POST_DATA中,以完成預約工做:

// 爲td綁定單擊事件
function BindTd() {
    $('.item').click(function () {
        var room_id = $(this).attr("room_id");
        var time_id = $(this).attr("time_id");

        // 取消預約
        if ($(this).hasClass("active")){
            // 若是點擊的標籤具備active類,直接刪除active類並清空內容
            $(this).removeClass("active").empty();
        }
        else if ($(this).hasClass("td_active")) {
            $(this).removeClass("td_active");
        }
        else {
            // 空白局域點擊  添加預約
            $(this).addClass("td_active");

            if (POST_DATA.ADD[room_id]){
                // 在數據中已經存有會議室信息,將新單元格time_id添加進數組
                POST_DATA.ADD[room_id].push(time_id)
            } else {
                // 在數據中沒有存過對應會議室記錄,直接將time_id對其賦值建立一個字典
                POST_DATA.ADD[room_id] = [time_id, ]
            }
        }
    })
}

  點擊兩個按鈕後,在頁面控制檯打印POST_DATA顯示以下:

  

(3)臨時預約取消數據處理

// 取消臨時預約
else if ($(this).hasClass("td_active")) {
    $(this).removeClass("td_active");
    // 點擊刪除臨時預約時添加的數據
    // POST_DATA.ADD[room_id].pop(); // 這個是刪除最後一個元素不對
    POST_DATA.ADD[room_id].splice(POST_DATA.ADD[room_id].indexOf(time_id),1)
}

   利用splice方法在數組中從指定位置開始刪除,且指定僅刪除一項。

(4)js數組操做經常使用方法

// shift:刪除原數組第一項,並返回刪除元素的值;若是數組爲空則返回undefined 
var a = [1,2,3,4,5];   
var b = a.shift(); //a:[2,3,4,5] b:1 

// pop:刪除原數組最後一項,並返回刪除元素的值;若是數組爲空則返回undefined 
var a = [1,2,3,4,5];   
var b = a.pop(); //a:[1,2,3,4] b:5 

// push:將參數添加到原數組末尾,並返回數組的長度 
var a = [1,2,3,4,5];   
var b = a.push(6,7); //a:[1,2,3,4,5,6,7] b:7  

// concat:返回一個新數組,是將參數添加到原數組中構成的 
var a = [1,2,3,4,5];   
var b = a.concat(6,7); //a:[1,2,3,4,5] b:[1,2,3,4,5,6,7] 

// splice(start,deleteCount,val1,val2,...):從start位置開始刪除deleteCount項,並從該位置起插入val1,val2,... 
var a = [1,2,3,4,5];   
var b = a.splice(2,2,7,8,9); //a:[1,2,7,8,9,5] b:[3,4]   
var b = a.splice(0,1); //同shift   
a.splice(0,0,-2,-1); var b = a.length; //同unshift   
var b = a.splice(a.length-1,1); //同pop   
a.splice(a.length,0,6,7); var b = a.length; //同push 

// reverse:將數組反序 
// sort(orderfunction):按指定的參數對數組進行排序 

// slice(start,end):返回從原數組中指定開始下標到結束下標之間的項組成的新數組
var a = [1,2,3,4,5];   
var b = a.slice(2,5); //a:[1,2,3,4,5] b:[3,4,5] 

// join(separator):將數組的元素組起一個字符串,以separator爲分隔符,省略的話則用默認用逗號爲分隔符
var a = [1,2,3,4,5];   
var b = a.join("|"); //a:[1,2,3,4,5] b:"1|2|3|4|5" 

二、發送AJAX

// 發送ajax
$(".keep").click(function () {
    $.ajax({
        url:"/book/",
        type:"POST",
        data:{
            csrfmiddlewaretoken: '{{ csrf_token }}',
            choose_date:CHOOSE_DATE,
            post_data:JSON.stringify(POST_DATA)
        },
        dataType:"json",
        success:function (data) {
            console.log(data);

            if(data.state){
                // 預約成功
                location.href=""
            }else {
                alert("預約的房間已經被預約");
                location.href=""
            }
        }
    })
});

  網絡編程本質是瀏覽器和服務器之間發送字符串。

POST請求
瀏覽器——————》server
    "請求首行\r\nContent-Type:url_encode\r\n\r\na=1&b=2"
    "請求首行\r\nContent-Typr:application/json\r\n\r\n("a":1, "b":2)"

在django的wsgi的request中:
    request.body:元數據 '{"a":1, "b":2}'
    
    if 請求頭中的Content-Type==url_encode:
        request.POST = 解碼a=1&b=2

  注意這裏是選擇在data中添加csrfmiddlewaretoken: '{{ csrf_token }}',來解決forbiden報錯。

三、使用日曆插件

  這一塊沒有視頻須要研究一下。

6、視圖處理圖書預約和取消

import datetime
import json

def book(request):
    print(request.POST)
    post_data = json.loads(request.POST.get("post_data"))  # {"ADD":{"1":["5"],"2":["5","6"]},"DEL":{"3":["9","10"]}}
    choose_date = request.POST.get("choose_date")

    res = {"state": True, "msg": None}
    try:
        # 添加預約
        # post_data["ADD"] : {"1":["5"],"2":["5","6"]}

        book_list = []
        for room_id, time_id_list in post_data["ADD"].items():

            for time_id in time_id_list:
                book_obj = Book(user=request.user, room_id=room_id, time_id=time_id, date=choose_date)
                book_list.append(book_obj)

        Book.objects.bulk_create(book_list)

        # 刪除預約
        from django.db.models import Q
        # post_data["DEL"]: {"2":["2","3"]}

        remove_book = Q()
        for room_id, time_id_list in post_data["DEL"].items():
            temp = Q()
            for time_id in time_id_list:
                temp.children.append(("room_id", room_id))
                temp.children.append(("time_id", time_id))
                temp.children.append(("user_id", request.user.pk))
                temp.children.append(("date", choose_date))
                remove_book.add(temp, "OR")
        if remove_book:
            Book.objects.filter(remove_book).delete()

    except Exception as e:
        res["state"] = False
        res["msg"] = str(e)

    return HttpResponse(json.dumps(res))

一、json.loads()

 

二、批量插入預訂數據

 

三、Q查詢

 

四、刪除預訂數據

相關文章
相關標籤/搜索