会议室预定系统
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)
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 }