一、目标及业务流程

期望效果:

业务流程:

  1. 用户登录
  2. 预定会议室
  3. 退订会议室
  4. 选择日期;今日以及以后日期

二、表结构设计和生成

1、models.py(用户继承AbstractUser)

from django.db import models
# Create your models here.
from django.db import models
from django.contrib.auth.models import AbstractUserclass 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.captionclass 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)

注意:

(1)Django中提供了AbstractUser类,可以用来自由定制需要的model

from django.contrib.auth.models import AbstractUserclass 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,且只能存key。

2、修改配置文件settings.py,覆盖默认的User模型

  Django允许你通过修改setting.py文件中的 AUTH_USER_MODEL 设置覆盖默认的User模型,其值引用一个自定义的模型。

AUTH_USER_MODEL = "app01.UserInfo"

  上面的值表示Django应用的名称(必须位于INSTALLLED_APPS中)和你想使用的User模型的名称。

注意:在创建任何迁移或者第一次运行 manager.py migrate 前设置 AUTH_USER_MODEL

  设置AUTH_USER_MODEL数据库结构有很大的影响。改变了一些会使用到的表格,并且会影响到一些外键和多对多关系的构造。在你有表格被创建后更改此设置是不被 makemigrations 支持的,并且会导致你需要手动修改数据库结构,从旧用户表中导出数据,可能重新应用一些迁移。

3、数据迁移及创建超级用户

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

  这里遇到了一个问题:创建项目时没有创建应用,手动通过manage.py startapp user创建子项目,修改AUTH_USER_MODEL后执行makemigrations一直报错,找不到app01。

  创建两个超级用户:

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

三、系统登录login

urls.py:

from django.contrib import admin
from django.urls import path
from app01 import viewsurlpatterns = [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 authdef 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。

四、index部分

1、引入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)

2、在数据库添加数据

  

  

3、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标签需要添加,因此此处没有闭合trhtmls += "<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 = Truebreakprint(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标签需要添加,因此此处没有闭合trhtmls += "<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标签需要添加,因此此处没有闭合trhtmls += "<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 datetimedef 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标签需要添加,因此此处没有闭合trhtmls += "<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 = Truebreakif 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>

显示效果如下:

  

五、前端部分数据处理(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: meizzvar 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>

1、点击事件预定和取消——组织数据

<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"

2、发送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报错。

3、使用日历插件

  这一块没有视频需要研究一下。

六、视图处理图书预定和取消

import datetime
import jsondef 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"] = Falseres["msg"] = str(e)return HttpResponse(json.dumps(res))

1、json.loads()

2、批量插入预订数据

3、Q查询

4、删除预订数据

转载于:https://www.cnblogs.com/xiugeng/p/9490830.html

会议室预订系统(meeting room booking system)相关推荐

  1. python 会议室预约系统 开源_开源会议室预订系统-MRBS安装使用教程

    开源会议室预订系统-MRBS简介 Meeting Room Booking System (MRBS) 是一个基于 PHP/MySQL 开发的,使用浏览器访问的会议室预订系统.使用区域对会议室进行分组 ...

  2. MRBS 会议室预订系统 完整汉化翻译 修改

    Meeting Room Booking System (MRBS) 是一个基于 PHP/MySQL 开发的,使用浏览器访问的开源会议室预订系统,很好用了.官网为 https://mrbs.sourc ...

  3. sharepoint 2010 会议室预订系统-资源预订系统

    由于现在有很多企业或者公司,其办公楼层会议室比较多,预订情况不能及时得知,为了能进一步规范和管理这些会议室资源,更好的提高办公会议室的资源使用率,提高组织者安排会议的效率,需要有一套比较成熟的会议室预 ...

  4. 使用sharepoint2010 分组日历制作会议室预订系统

    近期由于会议较多,各部门之间使用会议室时间冲突频繁发生,使沟通成本明显增加.为了规范 化管理会议室资源,提高会议效率,降低沟通成本,上线一套会议室管理系统势在必行. 现有生产环境中,拥有微软的shar ...

  5. python 会议室预约系统_基于django的会议室预订系统

    欢迎登录会议室预订系统 {% csrf_token %} 用户名 密码 登录 varhandlerPopup= function(captchaObj) {//成功的回调 captchaObj.onS ...

  6. 钉钉版会议室预订系统使用指南

    本文将介绍,如何使用钉钉版本启明星会议室预订系统. (1)登录系统. 当安装好会议室预订系统后,如果直接打开预订系统book,将直接跳转到钉钉的登录页面,所以,请先手动在浏览器里输入 login2.a ...

  7. java 会议室预订系统_java会议室管理系统

    因为项目采用的是模块式开发,主项目里面只有页面和公共配置,后台代码都在其它模块工程里面.模块代码我放在了项目里面grcd-code-resources文件夹下面压缩包,解压打开之后可以进行工程依赖.如 ...

  8. MRBS开源会议室预订系统安装

    MRBS系统官方网址  https://mrbs.sourceforge.io/ 最近在找一份开源的会议室预订系统,找了很多种,ASP,PHP的,测试发现MRBS无疑是最好的. 开源社区对其介绍如下: ...

  9. knn约会_出色的在线约会预订系统应具备的5个功能

    knn约会 People always look for ways to ease their day-to-day tasks. Whether it is something related to ...

最新文章

  1. 第二章、FastDFS单机搭建过程
  2. R语言自定义函数计算dataframe每列中的缺失值NA的个数、缺失值问题及其填充示例
  3. jupyter扩展插件Nbextensions的安装、使用
  4. Android:数据库增删改查、SQLite、ORM、Cursor
  5. 印刷 计算机控制系统,陶瓷印刷计算机直接制版控制系统设计与实现
  6. 详解JavaScript数组过滤相同元素的5种方法
  7. RHEL6.4下一键安装 Redmine
  8. 重磅!2020北京智源大会完整日程公布,4天19场高端AI论坛邀你参加
  9. Windows系统封装步骤
  10. @ConditionalOnProperty
  11. Ubuntu中禁用触摸板
  12. jQuery 实现消消乐
  13. cups ipp oracle,基于IPP的逐步打印服务器使用CUPS
  14. RSA的非对称加密,公钥加密私钥解密,本地测试
  15. TOGAF企业架构的主要内容——上海信息化培训中心
  16. 实操手册:如何在GKE上部署HTTP(S) Load Balancer及容器应用程式
  17. 利用MRT进行多年LAI数据(MOD15A2)拼接和投影转换
  18. linux如何调试elf程序,开发一个Linux调试器就需要了解ELF和DWARF
  19. 西瓜书第一、二章节笔记
  20. 今年十月最新语言排行榜

热门文章

  1. 大学生在校是做兼职好还是做副业好
  2. 计算机毕业设计(15)python毕设作品之校园教室图书馆座位预约系统
  3. 1.Spring Cloud 构建微服务应用程序之概览
  4. JAVA 订阅推送快递100物流消息(一)
  5. 数据库 -> 索引的基本原理
  6. 饿了么美团红包外卖cps分销裂变小程序搭建,外卖优惠券
  7. 201506050014袁华生
  8. 测试开发实战|如何利用 xUnit 框架对测试用例进行维护?
  9. 使用广播信道的数据链路层
  10. 隐性解析_开发移动应用程序的隐性成本