028 會議室預定設計與會議室預定程式碼
會議室預定設計
一、目標
- 會議室預定
二、業務流程
- 使用者登入
- 預定會議室
- 退訂會議室
- 選擇日期;今日以及以後日期
三、表結構設計
- 使用者表
- 會議室表
- 記錄表
使用者ID 會議室ID 時間 時間段
user_id room_id data timeline
1 1 2017-12-11 1
from django.db import models # Create your models here. class MeetingRoom(models.Model):'''會議室''' name = models.CharField(max_length=32,verbose_name="會議室名稱") class Meta: verbose_name_plural = "會議室" def __str__(self): return self.name class ReserveRecord(models.Model): '''預定記錄表''' data = models.DateField(verbose_name="預定日期") user = models.ForeignKey(to="UserInfo",verbose_name="預訂人") room = models.ForeignKey(to="MeetingRoom",verbose_name="預定房間") time1 = ( (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"), ) timeline = models.IntegerField(choices=time1,verbose_name="預定時間") class Meta: verbose_name_plural = "預訂記錄表" unique_together = ( ('data', 'timeline', 'room') ) def __str__(self): return self.user.username class UserInfo(models.Model): '''使用者資訊''' username = models.CharField(max_length=32,verbose_name="使用者名稱",unique=True) password = models.CharField(max_length=64,verbose_name="密碼") class Meta: verbose_name_plural = "使用者資訊" def __str__(self): return self.username
四、操作細節以及設計的知識點
=========================後端頁面=================
我們可以用ajax的方式,傳送請求。後端返回資料,直接在頁面中渲染。
如何生成這樣的資料
data = [
[{"text":"天上人間","attrs":{}},{"text":"海燕","attrs":{"room_id":1,"time_id":1,"class":"chosen"}},{"text":"","attrs":{"room_id":1,"time_id":1}},{"text":"","attrs":{"room_id":1,"time_id":1}},{"text":"","attrs":{"room_id":1,"time_id":1}}],
[{"text":"夏威夷","attrs":{}},{"text":"","attrs":{"room_id":2,"time_id":2}},{"text":"Frank","attrs":{"room_id":1,"time_id":1,"class":"chosen"}}],
[{"text":"馬爾地夫","attrs":{}},{"text":"","attrs":{"room_id":3,"time_id":3}},{"text":"","attrs":{"room_id":1,"time_id":1}}],
]
有可能有人已經預定了,當沒有chosen的時候就沒有預定.
預定資訊都放在預定表裡了
所以我們得去預定表裡面取一些資料
那麼怎麼獲取預定資訊呢?獲取指定日期所有的預定資訊(也就是這一天的所有預定資訊)
具體操作:
在資料庫裡面新增預定資訊
到底查那天的是不確定的,應該是使用者給發過來的,所以發ajax的時候得發過來一個日期
data:{choice_data:"2017-5-5"}
在views中,獲取日期,但是這個日期是有限制的,必須是大於等於當前的日期,如果是前幾天的就不能在選,都已經過去了,
當前日期等於....data型別
獲取的日期等於...str型別。所以要轉一下。
獲取到的是一個queryset集合[
OBJ(1,room_id,user_id.time_id.data)
OBJ(1,room_id,user_id.time_id.data)
OBJ(1,room_id,user_id.time_id.data)
]
檢測會議室在該時間段是否已預定
在上面這個資料存在則表示已經預定,不存在沒預定
方式一:
利用兩層迴圈來做,但是迴圈的效率不怎麼高,所以也可以用結構化資料的方式
for bk in recording_list: if room.id==bk.room.id and bk.timeline==tm[0]: td={"text":bk.user.username,"attrs":{"room_id":room.id,"time_id":tm[0],"class":"chosen"}} # 如果沒有預定就不加 tr.append(td)
下面是具體操作
1 def recording(request): 2 response = {"status":True,"msg":None,"data":None} 3 #檢視指定日期所有的預定資訊 4 ajax_date= request.GET.get("date") #字串型別 5 current_data = datetime.datetime.now().date() #日期型別 6 ajax_date = datetime.datetime.strptime(ajax_date, '%Y-%m-%d').date() 7 try: 8 if ajax_date < current_data: 9 raise Exception("查詢時間不能是以前的時間") 10 recording_list = models.ReserveRecord.objects.filter(data=ajax_date) 11 print(recording_list,"recording_list") 12 room_list = models.MeetingRoom.objects.all() 13 data = [] 14 for room in room_list: 15 tr = [] 16 tr.append({"text":room.name,"attrs":{}}) 17 for tm in models.ReserveRecord.time1: 18 # print(tm[1]) 19 td={"text":"","attrs":{"room_id":room.id,"time_id":tm[0]}} 20 #判斷該房間在該時間段被預定了沒有 21 # 如果預定了就加上{"class":"chosen"} 22 for bk in recording_list: 23 if room.id==bk.room.id and bk.timeline==tm[0]: 24 td={"text":bk.user.username,"attrs":{"room_id":room.id,"time_id":tm[0],"class":"chosen"}} # 如果沒有預定就不加 25 tr.append(td) 26 data.append(tr) 27 28 # data = [ 29 # [{"text":"天上人間","attrs":{}},{"text":"海燕","attrs":{"room_id":1,"time_id":1,"class":"chosen"}},{"text":"","attrs":{"room_id":1,"time_id":1}},{"text":"","attrs":{"room_id":1,"time_id":1}},{"text":"","attrs":{"room_id":1,"time_id":1}}], 30 # [{"text":"夏威夷","attrs":{}},{"text":"","attrs":{"room_id":2,"time_id":2}},{"text":"Frank","attrs":{"room_id":1,"time_id":1,"class":"chosen"}}], 31 # [{"text":"馬爾地夫","attrs":{}},{"text":"","attrs":{"room_id":3,"time_id":3}},{"text":"","attrs":{"room_id":1,"time_id":1}}], 32 # ] 33 response["data"] = data 34 except Exception as e: 35 response["status"] = True 36 response["msg"] = str(e) 37 38 return JsonResponse(response)View Code
吧[
OBJ(1,room_id,user_id.time_id.data)
OBJ(1,room_id,user_id.time_id.data)
OBJ(1,room_id,user_id.time_id.data)
]變成一個字典
查詢中字典的查詢速度是最快的
{
2: {
9: {'username': 'egon', 'user_id': 1}
}
}
1表示room_id,5表示time_id
ecrding_dict = {} for i in recording_list: if i.room_id not in recrding_dict: recrding_dict[i.room_id]={i.timeline:{"username":i.user.username,"user_id":i.user_id}} else: recrding_dict[i.room_id][i.timeline] = {i.timeline:{"username":i.user.username,"user_id":i.user_id}} print(recrding_dict)
然後看一下它的room_id和time_id在不在字典裡面。如果在裡面已經被預定了,否則沒有被預定
具體實現
def recording(request): response = {"status":True,"msg":None,"data":None} current_data = datetime.datetime.now().date() #日期型別 #檢視指定日期所有的預定資訊 try: ajax_date= request.GET.get("date") #字串型別 ajax_date = datetime.datetime.strptime(ajax_date, '%Y-%m-%d').date() if ajax_date < current_data: raise Exception("查詢時間不能是以前的時間") recording_list = models.ReserveRecord.objects.filter(data=ajax_date) #查詢的這一天的所有的記錄 print(recording_list,"recording_list") # [OBJ(1,room_id,user_id.time_id.data),OBJ(2,room_id,user_id.time_id.data)] recrding_dict = {} for i in recording_list: if i.room_id not in recrding_dict: recrding_dict[i.room_id]={i.timeline:{"username":i.user.username,"user_id":i.user_id}} else: recrding_dict[i.room_id][i.timeline] = {i.timeline:{"username":i.user.username,"user_id":i.user_id}} print(recrding_dict) room_list = models.MeetingRoom.objects.all() data = [] for room in room_list: tr = [] tr.append({"text":room.name,"attrs":{}}) for tm in models.ReserveRecord.time1: # print(tm[1]) # 方式二 # 判斷該房間在該時間段被預定了沒有, 如果預定了就加上{"class":"chosen"} if room.id in recrding_dict and tm[0] in recrding_dict[room.id]: td={"text":recrding_dict[room.id][tm[0]]["username"],"attrs":{"room_id":room.id,"time_id":tm[0],"class":"chosen"}} else: td = {"text": "", "attrs": {"room_id": room.id, "time_id": tm[0]}} tr.append(td) data.append(tr) response["data"] = data except Exception as e: response["status"] = True response["msg"] = str(e) return JsonResponse(response)
前端頁面
======================前端頁面===================== 今天日期怎麼獲取、: d = new Date() #當天日期 d.getFullYeat() #年 d.getMonth() #月 d.getDate() #日 =========給字串擴充套件的一個uuuu方法============ String.prototype.uuuu = function(){ return "zzzz" } =========給日期物件擴充套件的一個Format方法============ d = new Date() Date.prototype.Format = function(){ .. } ===============載入框================= 和模態框一樣,也有兩層(遮罩層,載入層) .shade { position: fixed; z-index: 1040; top: 0; left: 0; right: 0; bottom: 0; background-color: #999; filter: alpha(opacity=50); -moz-opacity: 0.5; opacity: 0.5; } .loading { position: fixed; z-index: 1050; top: 40%; left: 50%; height: 32px; width: 32px; margin: 0 0 0 -16px; background: url(/static/img/loading.gif); } 那麼什麼時候讓他顯示呢? 預設是隱藏的 當剛開始發ajax的時候載入,獲取成功之後就讓隱藏了 出錯之後也給讓載入 解決forbidden function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken')); } } });
圖片解析
待續具體操作、、、、、、、、、、
繫結完以後預定或者退訂
1、預定的時候加個樣式,當點完以後取消預定給移除了
2、如果是本來就有的,先把有的背景去掉,而且文字清空
3、點選儲存吧選中的以及取消過的都發到後臺,
我要預定那些,我要取消那些。要把這些資料傳送過去
我們通過樣式發過去有點麻煩,我們可以通過一個全域性變數發過去
POST——DATA = {
"ADD":{},
"DEL":{}
}
假如:
POST——DATA = {
"ADD":{
room_id time_id
4: [4,5]
},
"DEL":{}
}
現在來生成這樣的結構,如果4存在。
js中的{}物件如果key存在,就有值,如果不存在返回undified
4、當一開始預定了,然後又不預定給刪除了,這時的資料沒有在資料庫中,從add中吧資料刪除
5、js中的刪除指定的值, v= [1,2,3,4]
v.indexOf(3) #找到就找到,找不到就等於-1
當找到的時候用v.splice(index,1) #刪除索引位置的一個
6、增加的id有他,刪除的id也有他,先刪除還是先增加?
POST——DATA = {
"ADD":{
1:[5,6]
2:[5,6,7]
},
"DEL":{
1:[6,7]
}
}
先刪除後新增,因為這是還沒有資料庫呢。原來資料庫就已經有有值了,先從add,和del中刪除了,資料庫就不用再添加了。
完了批量新增其他的值
7、給儲存按鈕繫結事件
吧使用者預定記錄的資料傳送到後臺
傳送ajax請求
function initSaveEvent() {
$("#save").click(function () {
$.ajax({
url:"/recording/",
type:"post",
data:{
data:JSON.stringify(POST_DATA), //要傳送的使用者傳過來的時間
date:CHOISE_DATE, //傳送的日期時間
csrfmiddlewaretoken:'{{ csrf_token }}'
},
success:function (data) {
console.log(data);
if (data.status){
initRecoringInfo(CHOISE_DATE)
}
else {
alert(data.msg)
}
}
})
})
}
使用者選擇的日期date,怎麼拿呢?在來一個全域性變數
預設是CHOISE_DATE = new Date().Format("yyyy-MM-dd")
change 的時候會修改
function change(){
CHOISE_DATE = new Date().Format("yyyy-MM-dd")
initserverecoing(CHOISE_DATE)
}
8、csrf驗證的三種方式:
1、帶著資料發過去
2、從cookie中拿到,帶著請求頭髮給後臺
3、在發資料的時候{{ csrf_token }} #不推薦
詳見部落格:http://www.cnblogs.com/haiyan123/p/7837439.html
========================資料傳送到後臺以後======================
發過來的日期和當前的日期還是進行一個比較,
然後在後端處理資料,,該儲存的儲存,該刪除的刪除(刪除的時候用Q查詢,外面是或關係,裡面是or關係)
然後資料如果成功之後,再去傳送ajax請求,呼叫函式
三、涉及到的相關知識點:
1、使用者登入
使用者登入成功之後吧使用者id和使用者名稱設定在session或者cookie中
注意:設定cookie的時候要設定成簽名的cookie,也就是加密的cookie
obj = redirect("/index/") obj.set_cookie("id",user.id) #明文的cookie obj.set_signed_cookie("id",user.id,salt="aaaa") #密文的cookie return obj
2、一週沒免登入:也就是設定cookie和session的過期時間(預設是兩週)
主動設定超時時間:request.session.set_expiry(60 * 60 * 24 * 30)
3、判斷使用者是否已經登入,有兩種方式:
方式一:裝飾器(就有幾個函式的時候用裝飾器)
方式二:中介軟體(大型專案的時候用中介軟體)
4、寫功能的時候獲取並顯示資料
- 要麼在用模板渲染
- 要麼返回頁面,ajax獲取資料
5、前端傳送資料
- Form表單提交
- Ajax提交
會議室預定系統程式碼
1、models.py
1 from django.db import models 2 3 # Create your models here. 4 class MeetingRoom(models.Model): 5 '''會議室''' 6 name = models.CharField(max_length=32,verbose_name="會議室名稱") 7 class Meta: 8 verbose_name_plural = "會議室" 9 10 def __str__(self): 11 return self.name 12 13 class ReserveRecord(models.Model): 14 '''預定記錄表''' 15 data = models.DateField(verbose_name="預定日期") 16 user = models.ForeignKey(to="UserInfo",verbose_name="預訂人") 17 room = models.ForeignKey(to="MeetingRoom",verbose_name="預定房間") 18 time1 = ( 19 (1,"8.00"), 20 (2,"9.00"), 21 (3,"10.00"), 22 (4,"11.00"), 23 (5,"12.00"), 24 (6,"13.00"), 25 (7,"14.00"), 26 (8,"15.00"), 27 (9,"16.00"), 28 (10,"17.00"), 29 (11,"18.00"), 30 (12,"19.00"), 31 (13,"20.00"), 32 ) 33 timeline = models.IntegerField(choices=time1,verbose_name="預定時間") 34 class Meta: 35 verbose_name_plural = "預訂記錄表" 36 unique_together = ( 37 ('data', 'timeline', 'room') 38 ) 39 def __str__(self): 40 return self.user.username 41 42 class UserInfo(models.Model): 43 '''使用者資訊''' 44 username = models.CharField(max_length=32,verbose_name="使用者名稱",unique=True) 45 password = models.CharField(max_length=64,verbose_name="密碼") 46 class Meta: 47 verbose_name_plural = "使用者資訊" 48 49 def __str__(self): 50 return self.username
2、urls.py
1 """會議室預定 URL Configuration 2 3 The `urlpatterns` list routes URLs to views. For more information please see: 4 https://docs.djangoproject.com/en/1.11/topics/http/urls/ 5 Examples: 6 Function views 7 1. Add an import: from my_app import views 8 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 Class-based views 10 1. Add an import: from other_app.views import Home 11 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 Including another URLconf 13 1. Import the include() function: from django.conf.urls import url, include 14 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 """ 16 from django.conf.urls import url 17 from django.contrib import admin 18 from app01 import views 19 urlpatterns = [ 20 url(r'^admin/', admin.site.urls), 21 url(r'^index/$', views.index), 22 url(r'^recording/$', views.recording), 23 url(r'^login/$', views.login), 24 ]
3、views.py
1 from django.forms import Form 2 from django.forms import fields 3 from django.forms import widgets 4 from django.http.response import JsonResponse 5 from django.shortcuts import render,redirect 6 from app01 import models 7 # Create your views here. 8 import datetime 9 import json 10 # def index(request): 11 # #檢視所有會議室的名稱 12 # metting_list = models.ReserveRecord.time1 13 # print("4444444",metting_list) 14 # room_obj = models.MeetingRoom.objects.all() 15 # 16 # return render(request,"index.html",{"metting_list":metting_list,"room_obj":room_obj}) 17 18 class LoginForm(Form): 19 username = fields.CharField( 20 max_length=8, 21 required=True, 22 error_messages={ 23 "max_length":"使用者名稱長度不能大於8位", 24 "required":"使用者名稱不能為空", 25 }, 26 # label="使用者名稱", 27 # label_suffix=":", 28 widget=widgets.TextInput(attrs={"class":"form-control","placeholder":"username","id":"username"}) 29 ) 30 password = fields.CharField( 31 max_length=8, 32 min_length=3, 33 required=True, 34 error_messages={ 35 "max_length":"密碼長度不能大於8位", 36 "min_length":"密碼長度不能小於3位", 37 "required":"密碼不能為空", 38 }, 39 # label="密碼", 40 # label_suffix=":", 41 widget=widgets.PasswordInput(attrs={"class":"form-control","placeholder":"password","id":"password"})) 42 def login(request): 43 if request.method =="GET": 44 form = LoginForm() 45 return render(request,"login.html",{"form":form}) 46 else: 47 form = LoginForm(data=request.POST) 48 if form.is_valid(): 49 user = models.UserInfo.objects.filter(**form.cleaned_data).first() 50 if user: 51 request.session["userinfo"]={"id":user.id,"name":user.username} 52 return redirect("/index/") 53 # cookie的方式設定 54 # obj.set_cookie("name","zzz") 55 # obj.set_signed_cookie("id",user.id,salt="aaaa") 56 # obj.set_signed_cookie("id1",user.id) 57 # return obj 58 else: 59 form.add_error('password','密碼錯誤') 60 return render(request,"login.html",{"form":form}) 61 return render(request, "login.html", {"form": form}) 62 63 64 def index(request): 65 metting_list = models.ReserveRecord.time1 66 return render(request,"index.html",{"metting_list":metting_list}) 67 68 def recording(request): 69 response = {"status": True, "msg": None, "data": None} 70 if request.method == "GET": 71 current_data = datetime.datetime.now().date() #日期型別 72 #=======================獲取指定日期所有的預定資訊========================= 73 try: 74 ajax_date= request.GET.get("date") #字串型別 75 # print(ajax_date,"============") 76 ajax_date = datetime.datetime.strptime(ajax_date, '%Y-%m-%d').date() 77 # print("date....",ajax_date) 78 if ajax_date < current_data: 79 raise Exception("查詢時間不能是以前的時間") 80 recording_list = models.ReserveRecord.objects.filter(data=ajax_date) #查詢的這一天的所有的記錄 81 # print(recording_list,"recording_list") # [OBJ(1,room_id,user_id.time_id.data),OBJ(2,room_id,user_id.time_id.data)] 82 # 吧這樣的資料處理成字典的形式,提升查詢速度 83 # { 84 # 1:{ #room_id 85 # 2:{"username":2,"user_id":3} #2表示time_id 86 # } 87 # } 88 recrding_dict = {} 89 for i in recording_list: 90 if i.room_id not in recrding_dict: 91 recrding_dict[i.room_id]={i.timeline:{"username":i.user.username,"user_id":i.user_id}} 92 else: 93 # recrding_dict[i.room_id][i.timeline] = {i.timeline:{"username":i.user.username,"user_id":i.user_id}} 94 recrding_dict[i.room_id][i.timeline] = {"username":i.user.username,"user_id":i.user_id} 95 print('--------',recrding_dict) 96 #獲取所有的會議室資訊 97 room_list = models.MeetingRoom.objects.all() 98 #===========================生成會議室資訊======================== 99 data = [] 100 for room in room_list: 101 print(room) 102 tr = [] 103 tr.append({"text": room.name, "attrs": {}}) 104 for tm in models.ReserveRecord.time1: 105 td = {"text": "", "attrs": {"room_id": room.id, "time_id": tm[0]}} 106 if room.id in recrding_dict and tm[0] in recrding_dict[room.id]: 107 #已預訂,不確定是誰預定的,還得判斷一下 108 td['attrs']['class'] = "chosen" 109 if recrding_dict[room.id][tm[0]]['user_id'] == request.session["userinfo"]["id"]: 110 #如果是自己預定 111 td['text'] = '我' 112 else: 113 #如果是別人預定,加一個disabled屬性不可編輯,只有自己的能編輯 114 td['text'] = recrding_dict[room.id][tm[0]]['username'] 115 td['attrs']['disable'] = True 116 tr.append(td) 117 data.append(tr) 118 print('-==========',data) 119 response["data"] = data 120 except Exception as e: 121 response["status"] = True 122 response["msg"] = str(e) 123 else: 124 try: 125 current_date = datetime.datetime.now().date() 126 ajax_date = request.POST.get("date") 127 ajax_date = datetime.datetime.strptime(ajax_date, '%Y-%m-%d').date() 128 if ajax_date < current_date: 129 raise Exception("查詢時間不是當前的時間") 130 post_data = json.loads(request.POST.get("data")) #由於發過來的資料是字串,所以要轉一下才能是字典 131 print(post_data) #{'ADD': {'1': ['5', '4'], '2': ['4', '7']}, 'DEL': {'2': ['4']}}} 132 date = request.POST.get("date") #獲取日期 133 # print(date) #2017-12-12 134 # 拿到資料以後 135 # 如果time_id在ADD裡面有,在Del裡面也有值,就刪除了,因為資料庫裡面已經有值了。就直接把add裡的和del裡的刪除就行了 136 for room_id ,time_list in post_data["DEL"].items(): 137 if room_id not in post_data["ADD"]: 138 continue 139 else: 140 for time_id in list(time_list): 141 if time_id in post_data["ADD"][room_id]: 142 post_data["ADD"][room_id].remove(time_id) 143 post_data["DEL"][room_id].remove(time_id) 144 # print(post_data) 145 #新增資料 146 reserverecord_obj_list = [] 147 for room_id ,time_list in post_data["ADD"].items(): 148 for time_id in time_list: 149 # models.ReserveRecord.objects.create(room_id=room_id,time_id=time_id,date=date,user=request.session["userinfo"]["id"]) 150 obj = models.ReserveRecord(room_id=room_id,timeline=time_id,data=date,user_id=request.session["userinfo"]["id"]) 151 reserverecord_obj_list.append(obj) 152 models.ReserveRecord.objects.bulk_create(reserverecord_obj_list) 153 154 #刪除會議室預定資訊 155 from django.db.models import Q 156 remove_reserverecord = Q() 157 for room_id,time_list in post_data["DEL"].items(): 158 for time_id in time_list: 159 temp = Q() 160 temp.connector = "AND" 161 temp.children.append(("user_id",request.session["userinfo"]["id"])) 162 temp.children.append(("data",date)) 163 temp.children.append(("room_id",room_id)) 164 temp.children.append(("timeline",time_id)) 165 166 remove_reserverecord.add(temp,"OR") 167 if remove_reserverecord: 168 print(models.ReserveRecord.objects.filter(remove_reserverecord)) 169 models.ReserveRecord.objects.filter(remove_reserverecord).delete() 170 # print(remove_reserverecord,"remove_reserverecord") 171 except Exception as e: 172 response["status"] = False 173 response["msg"] = str(e) 174 return JsonResponse(response)View Code
4、templates
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width"> 7 <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> 8 <script src="/static/jquery-3.2.1.min.js"></script> 9 <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> 10 <title>Title</title> 11 <style> 12 .container { 13 margin-top: 100px; 14 } 15 </style> 16 </head> 17 <body> 18 <form action="/login/" method="post" novalidate> 19 {% csrf_token %} 20 <div class="container"> 21 <h3 style="text-align: center">請先登入</h3> 22 <div class="row"> 23 <div class="col-md-4 col-md-offset-4"> 24 <div class="form-group"> 25 <label for="username">使用者名稱</label> 26 {{ form.username }} 27 <p style="color: red">{{ form.errors.username.0 }}</p> 28 </div> 29 <div class="form-group"> 30 <label for="password">密碼</label> 31 {{ form.password }} 32 <p style="color: red">{{ form.errors.password.0 }}</p> 33 </div> 34 <input type="submit" value="登入" class="btn btn-success col-sm-7 col-md-offset-2"> 35 </div> 36 </div> 37 38 </div> 39 40 </form> 41 </body> 42 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width"> 7 <title>Title</title> 8 <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> 9 <link rel="stylesheet" href="/static/css/index.css"> 10 <link rel="stylesheet" href="/static/bootstrap-datetimepicker-master/css/bootstrap-datetimepicker.css"> 11 <script src="/static/jquery-3.2.1.min.js"></script> 12 <script src="/static/bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js"></script> 13 <script src="/static/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.fr.js"></script> 14 <script src="/static/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-CN.js"></script> 15 </head> 16 <body> 17 <div class="container"> 18 <div class="row"> 19 <div class="col-md-11"> 20 <h1>會議室預定</h1> 21 <div class="data pull-right"> 22 <button class="btn btn-primary" id="save">儲存</button> 23 </div> 24 {# 日期#} 25 <div class='col-sm-4 pull-right'> 26 <div class="form-group"> 27 <div class='input-group date' id='datetimepicker2' placeholder="請選擇日期"> 28 <input type='text' class="form-control"/> 29 <span class="input-group-addon"> 30 <span class="glyphicon glyphicon-calendar"></span> 31 </span> 32 </div> 33 </div> 34 </div> 35 {# 表格#} 36 <div> 37 <table class="table table-bordered"> 38 <thead> 39 <th>會議室</th> 40 {% for metting in metting_list %} 41 <th>{{ metting.1 }}</th> 42 {% endfor %} 43 </thead> 44 <tbody id = "tBody"> 45 {# 方式一:也可以這樣渲染#} 46 {# {% for room in room_obj %}#} 47 {# <tr>#} 48 {# <td>{{ room.name }}</td>#} 49 {# {% for metting in metting_list %}#} 50 {# <td></td>#} 51 {# {% endfor %}#} 52 {# </tr>#} 53 {# {% endfor %}#} 54 {# 方式二#} 55 {# 傳送ajax請求渲染#} 56 57 </tbody> 58 </table> 59 </div> 60 {# 載入框#} 61 <div class="shade hide"></div> 62 <div class="loading hide"></div> 63 </div> 64 </div> 65 </div> 66 <script> 67 //對Date的擴充套件 68 // 對Date的擴充套件,將 Date 轉化為指定格式的String 69 // 月(M)、日(d)、小時(h)、分(m)、秒(s)、季度(q) 可以用 1-2 個佔位符, 70 // 年(y)可以用 1-4 個佔位符,毫秒(S)只能用 1 個佔位符(是 1-3 位的數字) 71 // 例子: 72 // (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423 73 // (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18 74 Date.prototype.Format = function (fmt) { //author: meizz 75 var o = { 76 "M+": this.getMonth() + 1, //月份 77 "d+": this.getDate(), //日 78 "h+": this.getHours(), //小時 79 "m+": this.getMinutes(), //分 80 "s+": this.getSeconds(), //秒 81 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 82 "S": this.getMilliseconds() //毫秒 83 }; 84 if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 85 for (var k in o) 86 if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 87 return fmt; 88 }; 89 90 $(function(){ //一開始載入的時候執行這個函式 91 initDatepickle(); 92 initRecoringInfo(new Date().Format("yyyy-MM-dd")); 93 initTdEvent(); 94 initSaveEvent(); 95 }); 96 97 POST_DATA = { 98 "ADD":{}, 99 "DEL":{} 100 }; 101 //時間控制元件初始化 102 function initDatepickle() { 103 $('#datetimepicker2').datetimepicker({ 104 minView: "month",//設定只顯示到月份 105 format: 'yyyy-mm-dd',//顯示格式 106 {# autoclose: true,//選完自動關閉#} 107 todayBtn: true, 108 language:"zh-CN", 109 startDate: new Date(), //以前的日期不能點 110 bootcssVer:3 //小箭頭 111 }).on('changeDate', changeDate); 112 } 113 //點選日期外掛的時候改變的函式 114 function changeDate(ev) { 115 {# console.log(ev.date); //Wed Dec 13 2017 20:43:08 GMT+0800 (中國標準時間)#} 116 CHOISE_DATE = ev.date.Format("yyyy-MM-dd"); //拿到的是外掛的日期 117 initRecoringInfo(CHOISE_DATE); 118 119 } 120 121 CHOISE_DATE = new Date().Format("yyyy-MM-dd"); //當change的時候會修改日期,它拿到的是當前的日期 122 //獲取預定記錄傳送ajax請求 123 function initRecoringInfo(date) { //這裡穿進來的date就是上面轉換成字串的時間 124 {# 剛開始傳送ajax的時候載入#} 125 $(".shade,.loading").removeClass("hide"); 126 $(function () { 127 $.ajax({ 128 url: "/recording/", 129 type: "get", 130 data: {"date": date}, 131 success: function (data) { 132 $(".shade,.loading").addClass("hide"); 133 if (data.status) { 134 $("#tBody").empty(); 135 $.each(data.data, function (i, item) { 136 {# console.log(i,item);#} 137 var $tr = $("<tr>"); 138 $.each(item, function (j, k) { 139 {# console.log(j,k);#} 140 var $td = $("<td>"); 141 $td.text(k.text); 142 $.each(k.attrs, function (m, n) { 143 console.log(m, n); 144 $td.attr(m, n) 145 }); 146 $tr.append($td); 147 {# if (k.chosen){#} 148 {# $("class").addClass("chosen")#} 149 {# }#} 150 }); 151 $("#tBody").append($tr); 152 }); 153 154 //吧del,add裡面有的內容清空 155 CHOSEN_DATE = new Date().Format('yyyy-MM-dd'); 156 POST_DATA = { 157 DEL:{}, 158 ADD:{} 159 }; 160 } 161 else { 162 alert(data.msg) 163 } 164 }, 165 error:function () { 166 $(".shade,.loading").removeClass("hide"); 167 alert("異常錯誤") 168 } 169 }) 170 }) 171 } 172 173 //給td繫結事件,處理資料 174 function initTdEvent(){ 175 //事件委派 176 $("tBody").on("click","td[time_id][disable!='true']",function () { 177 //新增一個樣式 178 var room_id = $(this).attr("room_id"); 179 var time_id = $(this).attr("time_id"); 180 if ($(this).hasClass("chosen")){ 181 $(this).removeClass("chosen"); 182 $(this).text(""); 183 //退訂room_id = 1 ,time_id = 5的 184 if (POST_DATA.DEL[room_id]) { 185 //如果有room_id,就新增一個time_id 186 POST_DATA.DEL[room_id].push(time_id) 187 }else { 188 POST_DATA.DEL[room_id] = [time_id] 189 } 190 } 191 else if ($(this).hasClass("temp")){ 192 //取消預定 193 $(this).removeClass("temp"); 194 //從add中吧資料刪除(先找到索引,然後如果存在就刪除) 195 var index = POST_DATA.ADD[room_id].indexOf(time_id); 196 if (index!==-1) { 197 POST_DATA.ADD[room_id].splice(index,1) //索引為n的刪除一個 198 } 199 }else { 200 //要預定,吧預定的結果新增進去 201 $(this).addClass("temp"); 202 if (POST_DATA.ADD[room_id]) { 203 //如果有room_id,就新增一個time_id 204 POST_DATA.ADD[room_id].push(time_id) 205 }else { 206 POST_DATA.ADD[room_id] = [time_id] 207 } 208 } 209 }) 210 } 211 212 //通過ajax想後臺發資料 213 function initSaveEvent() { 214 $("#save").click(function () { 215 $.ajax({ 216 url:"/recording/", 217 type:"post", 218 data:{ 219 data:JSON.stringify(POST_DATA), //要傳送的使用者傳過來的時間 220 date:CHOISE_DATE, //傳送的日期時間 221 csrfmiddlewaretoken:'{{ csrf_token }}' 222 }, 223 224 success:function (data) { 225 console.log(data); 226 if (data.status){ 227 initRecoringInfo(CHOISE_DATE) 228 } 229 else { 230 alert(data.msg) 231 } 232 } 233 }) 234 }) 235 } 236 </script> 237 </body> 238 </html>
1 table{ 2 margin-top: 80px; 3 } 4 td{ 5 height: 80px; 6 } 7 .chosen{ 8 background-color: gold; 9 } 10 .shade { 11 position: fixed; 12 z-index: 1040; 13 top: 0; 14 left: 0; 15 right: 0; 16 bottom: 0; 17 background-color: #999; 18 filter: alpha(opacity=50); 19 -moz-opacity: 0.5; 20 opacity: 0.5; 21 } 22 23 .loading { 24 position: fixed; 25 z-index: 1050; 26 top: 40%; 27 left: 50%; 28 height: 32px; 29 width: 32px; 30 margin: 0 0 0 -16px; 31 background: url(/static/img/loading.gif); 32 } 33 .temp{ 34 background-color: salmon; 35 }