mrbs - 初识
一、mrbs
mrbs:(meeting room booking system)
会议室预订系统
二、效果
三、models
from django.db import models # Create your models here. 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) room = models.ForeignKey("Room", on_delete=models.CASCADE) date = models.DateField() time_choice = ( (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_choice) class Meta: unique_together = ( ('room','date','time_id'), ) def __str__(self): return str(self.user)+'预订了'+str(self.room)
知识点:
1.AbstractUser
AUTH_USER_MODEL = "app01.UserInfo"
class UserInfo(AbstractUser):
tel = models.CharField(max_length=32)
2.联合唯一 (time_choice)
time_choice = (
(1,'8:00'),
...
) 存的是key 显示的是value,且只能存key
time_id = models.IntegerField(choices=time_choice)
class Meta:
unique_together = (
('room','date','time_id'),
)
3.makemigrations / migrate
4.admin.py
admin.site.register(UserInfo)
admin.site.register(Book)
admin.site.register(Room)
5.createsuperuser
yuan yuan1234 / alex alex1234
四、login
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} 用户名:<input type="text" name="user"> 密码: <input type="password" name="pwd"> <input type="submit"> </form> </body> </html>
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), ]
from django.shortcuts import render,HttpResponse,redirect 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 return redirect('/index/') return render(request,'login.html')
知识点:
1.auth
from django.contrib import auth
user = auth.authenticate(username = user,password = pwd )
if user:
auth.login(request,user) # request.user
return redirect('/index/')
五、index
知识点:
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>会议室时间</th>
{% for time in time_choice %}
<th>{{ time.1 }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{{ htmls|safe }}
</tbody>
</table>
1.后台渲染html,不在模板处理数据,因为后台更方便一些
time_choice = Book.time_choice
room_list = Room.objects.all()
# 当天
date = datetime.datetime.now().date() # 年月日 datefield = datetime.datetime()
book_date = request.GET.get('book_date', date)
book_list = Book.objects.filter(date=book_date)
2.htmls
htmls = ""
for room in room_list:
htmls += "<tr><td>" + room.caption + "(" + str(room.num) + ")</td>"
for time in time_choice:
flag = False
for book in book_list:
if book.room.pk == room.pk and book.time_id == time[0]:
# 意味这个单元格已被预定
flag = True
break
if flag:
if request.user.pk == book.user.pk:
htmls += "<td class='active item' room_id=" + str(room.pk) + " time_id=" + str(
time[0]) + ">" + book.user.username + "</td>"
else:
htmls += "<td class='another_active item' room_id=" + str(room.pk) + " time_id=" + str(
time[0]) + ">" + book.user.username + "</td>"
else:
htmls += "<td class='item' room_id=" + str(room.pk) + " time_id=" + str(time[0]) + "></td>"
htmls += '</tr>'
print(htmls)
六、book
前端 组织 数据:
// 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')){
$(this).removeClass('active').empty();
if(POST_DATA.DEL[room_id]){
POST_DATA.DEL[room_id].push(time_id)
}else{
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]){
POST_DATA.ADD[room_id].push(time_id)
}else{
POST_DATA.ADD[room_id] = [time_id];
}
}
})
}
BindTd();
//发送 ajax
$('.keep').click(function () {
$.ajax({
url:'/book/',
type:'post',
headers:{"X-CSRFToken":$.cookie('csrftoken')},
data:{
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=""
}
}
})
});
。。。
后台 处理 数据:
1. json.loads()
2. 批量插入预订 数据
3. Q查询
4. 删除预订 数据
import json
def book(request):
post_data = json.loads(request.POST.get('post_data'))
# {'ADD': {'1': ['5', '7'], '3': ['4']}, 'DEL': {'2': ['9']}}
choose_date = request.POST.get("choose_date")
res = {"state": True, "msg": None}
try:
# 添加预订
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))
方式1:
q=Q()
q.connection="or"
q.children.append("pk",1)
q.children.append("user_id",1)
q.children.append("room_id",1)
Book.objects.filter(q)
方式2:
Book.objects.filter(Q(pk=1)|Q(user_id=1)|Q(room_id=1))
七、code
from django.shortcuts import render,HttpResponse,redirect 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 return redirect('/index/') return render(request,'login.html') from .models import * import datetime def index(request): time_choice = Book.time_choice room_list = Room.objects.all() # 当天 date = datetime.datetime.now().date() # 年月日 datefield = datetime.datetime() book_date = request.GET.get('book_date', date) book_list = Book.objects.filter(date=book_date) print('book_list', book_list) htmls = "" for room in room_list: htmls += "<tr><td>" + room.caption + "(" + str(room.num) + ")</td>" for time in time_choice: flag = False for book in book_list: if book.room.pk == room.pk and book.time_id == time[0]: # 意味这个单元格已被预定 flag = True break if flag: if request.user.pk == book.user.pk: htmls += "<td class='active item' room_id=" + str(room.pk) + " time_id=" + str( time[0]) + ">" + book.user.username + "</td>" else: htmls += "<td class='another_active item' room_id=" + str(room.pk) + " time_id=" + str( time[0]) + ">" + book.user.username + "</td>" else: htmls += "<td class='item' room_id=" + str(room.pk) + " time_id=" + str(time[0]) + "></td>" htmls += '</tr>' print(htmls) return render(request, 'index.html', locals()) import json def book(request): post_data = json.loads(request.POST.get('post_data')) # {'ADD': {'1': ['5', '7'], '3': ['4']}, 'DEL': {'2': ['9']}} choose_date = request.POST.get("choose_date") res = {"state": True, "msg": None} try: # 添加预订 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))
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css"> <script src="/static/js/jquery-1.12.4.min.js"></script> <script src="/static/js/jquery.cookie.js"></script> <script src="/static/datetimepicker/bootstrap-datetimepicker.min.js"></script> <script src="/static/datetimepicker/bootstrap-datetimepicker.zh-CN.js"></script> <style type="text/css"> .active{background-color: green!important; color: white;} .another_active{background-color: #336699;color: white;} .td_active{background-color: lightblue;} </style> </head> <body> <h3>会议室预订,欢迎:{{ request.user.username }}</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 in time_choice %} <th>{{ time.1 }}</th> {% endfor %} </tr> </thead> <tbody> {{ htmls|safe }} </tbody> </table> <button class="btn btn-success pull-right keep">保存</button> <script type="text/javascript"> // 日期格式化方法 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')){ $(this).removeClass('active').empty(); if(POST_DATA.DEL[room_id]){ POST_DATA.DEL[room_id].push(time_id) }else{ 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]){ POST_DATA.ADD[room_id].push(time_id) }else{ 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', headers:{"X-CSRFToken":$.cookie('csrftoken')}, data:{ 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> </body> </html>