会议室预定:
#需求
会议室功能: 1.登录后才能进去。 2.领导高层才能进去。 3.预定过的不能再预定 4.按照日期显示预定位置 5.预定表 一对一 用户 <---> 房间 一对一 时间字段 user字段 房间字段
表的设计
model.py
# (用户表、房间表、预定表) room,time_id,date 需要联合唯一
# 保证所有预定位置是唯一,如果重复出现就会报错
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_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) class Meta: # 联合唯一是为了保证数据保存的时候 # -p一旦其中有一个数据错误就报错 unique_together = ( ('room', 'date', 'time_id'), ) def __str__(self): return str(self.user) + '预定了' + str(self.room)
视图层
view.py
# 有登陆、主页、ajax过来创建删除表视图函数,写业务逻辑,写tr和td标签
from django.shortcuts import render, redirect, HttpResponse from django.http import JsonResponse from app01.models import Book, Room from app01 import models # Create your views here. from django.contrib import auth import json 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) return redirect('/index/') return render(request, 'login.html') def index(request): time_choices = Book.time_choices room_list = Room.objects.all() import datetime # 当前日期 now = datetime.datetime.now().date() html = '' for room in room_list: html += '<tr><td>{}({})</td>'.format(room.caption, room.num) for time_choice in time_choices: # 当前日期 book_obj = Book.objects.filter(room_id=room.pk, date=now, time_id=time_choice[0]).first() if book_obj: if request.user.pk == book_obj.user.pk: td = '<td class="now_checked" room_id={} time_id={}>{}</td>'.format(room.pk, time_choice[0], book_obj.user.username) else: td = '<td class="orther_checked" room_id={} time_id={}>{}</td>'.format(room.pk, time_choice[0], book_obj.user.username) else: td = '<td class="item" room_id={} time_id={}></td>'.format(room.pk, time_choice[0]) html += td html += '</tr>' return render(request, 'index.html', locals()) def create_book(request): data = json.loads(request.POST.get('data')) date = request.POST.get('date') # 添加预定 add_data = data.get('ADD') # print(add_data) ret = {'state': True} try: book_list = [] for room_id, time_id_list in add_data.items(): for time_id in time_id_list: book = Book(user=request.user, room_id=room_id, time_id=time_id, date=date) book_list.append(book) models.Book.objects.bulk_create(book_list) except Exception as e: ret['state'] = False # 删除预定 del_data = data.get("DEL") print(del_data) for room_id, time_id_list in del_data.items(): for time_id in time_id_list: models.Book.objects.filter(user=request.user, room_id=room_id, time_id=time_id, date=date).delete() return JsonResponse(ret)
前端页面
# index.html
# 渲染数据和td在view里面做,html里面只做js操作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>会议室</title> <link rel="stylesheet" href="../static/bootstrap-3.3.7/css/bootstrap.min.css"> </head> <body> <script src="../static/jquery-3.3.1.min.js"></script> <script src="../static/bootstrap-3.3.7/js/bootstrap.min.js"></script> <style> /*当前用户颜色*/ .now_checked { background-color: slategray; text-align: center; } /*其他用户颜色*/ .orther_checked { background-color: #ac2925; text-align: center; } /*当前点击选定颜色*/ .current_color { background-color: #31b0d5; } </style> <div class="container"> <hr> <div class="row"> <h1>会议室预定</h1> <table class="table table-bordered"> <thead> <tr> <th>会议室/时间</th> {% for time in time_choices %} <th>{{ time.1 }}</th> {% endfor %} </tr> </thead> <tbody> {{ html|safe }} <!--第一种渲染方式在前端写html--> {# {% for room in room_list %}#} {# <tr>#} {# <td>{{ room.caption }}({{ room.num }})</td>#} {# {% for time_choice in time_choices %}#} {# <td room_id="{{ room.pk }}" time_id="{{ time_choice.0 }}"></td>#} {# {% endfor %}#} {##} {# </tr>#} {# {% endfor %}#} </tbody> </table> {% csrf_token %} <button class="save btn btn-success col-md-offset-10">保存</button> </div> </div> <script> // 给Date对象添加Format属性 Date.prototype.Format = 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; }; // 绑定选定事件 $('body').on('click', '.item', function () { $(this).toggleClass('current_color'); }); // 取消预定事件 $('.now_checked').click(function () { // 删除当前颜色清空文本内容 $(this).removeClass('now_checked').html(''); // 给取消预订的td添加一个class $(this).addClass("cancel_td") }); // 保存事件 // 给需要发送的数据设计数据结构 DATA = { ADD:{}, DEL:{} }; $('.save').click(function () { // 循环所以需要选定的数据 $('.current_color').each(function (index, ele) { console.log(index, ele, $(ele).attr('room_id')); var room_id = $(ele).attr('room_id'); var time_id = $(ele).attr('time_id'); if (DATA.ADD.hasOwnProperty(room_id)){ DATA.ADD[room_id].push(time_id) }else{ DATA.ADD[room_id] = [time_id] } }); // 循环所有需要取消的数据 $('.cancel_td').each(function (index, ele) { var room_id = $(ele).attr('room_id'); var time_id = $(ele).attr('time_id'); if (DATA.DEL.hasOwnProperty(room_id)){ DATA.DEL[room_id].push(time_id); }else{ DATA.DEL[room_id]=[time_id]; } }); // 创建当前时间对象 date = new Date(); // ajax发送数据过去服务端 $.ajax({ url:"/create_book/", type:'post', data:{ csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(), data:JSON.stringify(DATA), date:date.Format('yyyy-MM-dd') }, success:function (data) { if (data.state){ console.log(data.state); location.href="" } } }); }); </script> </body> </html>