会议室预定设计

一、目标

- 会议室预定

二、业务流程

- 用户登录

- 预定会议室

- 退订会议室

- 选择日期;今日以及以后日期

三、表结构设计

- 用户表

- 会议室表

- 记录表

用户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)


下面是具体操作

028 会议室预定设计与会议室预定代码_django028 会议室预定设计与会议室预定代码_bootstrap_02

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'));             }         }     });


图片解析

028 会议室预定设计与会议室预定代码_bootstrap_03

待续具体操作、、、、、、、、、、


绑定完以后预定或者退订

  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 }} #不推荐

========================数据发送到后台以后======================

发过来的日期和当前的日期还是进行一个比较,

然后在后端处理数据,,该保存的保存,该删除的删除(删除的时候用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

View Code

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 ]

View Code

3、views.py

028 会议室预定设计与会议室预定代码_django028 会议室预定设计与会议室预定代码_bootstrap_02

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 }