会议室预定
会议室预定介绍
1. 目标:会议室预定
2. 业务流程:
- 用户登录
- 预定会议室
- 退订会议室
- 选择日期:今日以及以后日期
3. 数据库表设计:
- 用户表
- 会议室表
- 关系表:
用户ID 会议室ID 时间 时间段
1 1 2017-12-11 1
from django.db import models class UserInfo(models.Model): name = models.CharField(verbose_name='用户姓名', max_length=32) password = models.CharField(verbose_name='密码', max_length=32) class MeetingRoom(models.Model): title = models.CharField(verbose_name='会议室', max_length=32) class Booking(models.Model): user = models.ForeignKey(verbose_name='用户', to='UserInfo') room = models.ForeignKey(verbose_name='会议室', to='MeetingRoom') booking_date = models.DateField(verbose_name='预定日期') # time_choices = ( # (1, '8:30 - 9:00'), # (2, '9:00 - 9:30'), # (3, '9:30 - 10:00'), # (4, '10:00 - 10:30'), # (5, '10:30 - 11:00'), # (6, '11:00 - 11:30'), # (7, '11:30 - 12:00'), # (8, '12:00 - 12:30'), # (9, '12:30 - 13:00'), # (10, '13:00 - 13:30'), # (11, '13:30 - 14:00'), # (12, '14:00 - 14:30'), # (13, '14:30 - 15:00'), # (14, '15:00 - 15:30'), # (15, '15:30 - 16:00'), # (16, '16:00 - 16:30'), # (17, '16:30 - 17:00'), # (18, '17:00 - 17:30'), # (19, '17:30 - 18:00'), # (20, '18:00 - 18:30'), # (21, '18:30 - 19:00'), # (22, '19:00 - 19:30'), # (23, '19:30 - 20:00'), # (24, '20:00 - 20:30'), # ) 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'), ) booking_time = models.IntegerField(verbose_name='预定时间段', choices=time_choices) class Meta: unique_together = ( ('booking_date', 'booking_time', 'room') )
登陆验证
class LoginForm(Form): name = fields.CharField( required=True, error_messages={'required': '用户名不能为空'}, widget=widgets.TextInput(attrs={'class': 'form-control', 'placeholder': '用户名', 'id': 'name'}) ) password = fields.CharField( required=True, error_messages={'required': '密码不能为空'}, widget=widgets.PasswordInput(attrs={'class': 'form-control', 'placeholder': '密码', 'id': 'password'}) ) rmb = fields.BooleanField(required=False, widget=widgets.CheckboxInput(attrs={'value': 1})) def md5(val): import hashlib m = hashlib.md5() m.update(val.encode('utf-8')) return m.hexdigest() def auth(func): def inner(request, *args, **kwargs): user_info = request.session.get('user_info') if not user_info: return redirect('/login/') return func(request, *args, **kwargs) return inner def login(request): """ 用户登录 """ if request.method == "GET": form = LoginForm() return render(request, 'login.html', {'form': form}) else: form = LoginForm(request.POST) if form.is_valid(): rmb = form.cleaned_data.pop('rmb') form.cleaned_data['password'] = md5(form.cleaned_data['password']) user = models.UserInfo.objects.filter(**form.cleaned_data).first() if user: request.session['user_info'] = {'id': user.id, 'name': user.name} if rmb: request.session.set_expiry(60 * 60 * 24 * 30) return redirect('/index/') else: form.add_error('password', '密码错误') return render(request, 'login.html', {'form': form}) else: return render(request, 'login.html', {'form': form})
涉及知识点:
1. hashlib模块 ----密码密文处理
2. 用户登录验证
一般设置session或者cookie,如果是设置cookie,要用密文的方式
request.set_signed_cookie(key,value,salt='加密盐',...)
3.主动设置超时时间:
request.session.set_expiry(60 * 60 * 24 * 30)
- 判断用户是否已经登录
- 装饰器,需要处理的函数较少,用装饰器即可
- 中间件,需要处理的函数较多时采用
- 功能
- 获取并显示数据的两种方式
- 模板渲染
- 返回页面,ajax获取数据
- 发送数据的两种方式
- Form表单提交
- Ajax提交
前端页面
加载框的应用
基于bootstrap的datetimepicker时间插件
function initDatepicker() { $('#datetimepicker11').datetimepicker({ minView: "month", //指定日历显示最小为月 language: "zh-CN", //汉化日历显示 sideBySide: true, format: 'yyyy-mm-dd', //指定显示格式 bootcssVer: 3, startDate: new Date() //指定起始日期 //autoclose: true, //确认日期即关闭日历 }).on('changeDate', changeDate); //绑定时间,日期改变则执行changeDate函数 } //改变日期执行的函数 function changeDate(ev) { CHOSEN_DATE = ev.date.Format('yyyy-MM-dd'); initBookingInfo(CHOSEN_DATE); }
js方法扩展:
prototype 属性可以向对象添加自定义的属性和方法。
String.prototype.xxx = function(arg){
sdf
}
val ="asdf"
val.xxx(arg)
Date.prototype.Format = function (fmt){
...
}
v = new Date()
v.Format('xx')
自定义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; };
从数组中删除指定元素
var timeIndex = SELECTED_ROOM.add[roomId].indexOf(timeId); //找到当前取消选中的在add[roomId]中的索引值,如果不存在索引值默认为-1 if (timeIndex !== -1) { SELECTED_ROOM.add[roomId].splice(timeIndex, 1); //从列表中删除当前取消选中的timeId值 }
JavaScript中的数组类似于Python中的列表
常见功能:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
obj.length 数组的大小obj.push(ele) 尾部追加元素obj.pop() 尾部获取一个元素obj.unshift(ele) 头部插入元素obj.shift() 头部移除元素obj.splice(start, deleteCount, value, ...) 插入、删除或替换数组的元素 obj.splice(n,0,val) 指定位置插入元素 obj.splice(n,1,val) 指定位置替换元素 obj.splice(n,1) 指定位置删除元素obj.slice( ) 切片obj.reverse( ) 反转obj.join(sep) 将数组元素连接起来以构建一个字符串obj.concat(val,..) 连接数组obj.sort( ) 对数组元素进行排序 |
ajax发送数据时,如果需要发送json字符串但又希望能在request.POST里拿到值,可以采用发送字典的方式
data: {date: CHOSEN_DATE, data: JSON.stringify(SELECTED_ROOM)}, //这样可以将部分数据json格式化,后端依然可以用request.POST接收数据
否则后端只能在request.body里取值,取出来时还需要先进行解码request.body.decode以后才能用dump.loads
前端发送日期到后端,后端把日期取出来是字符串格式,需要转换成时间对象
current_date = datetime.datetime.now().date() #将当前日期转换成年月日的形式 if request.method == "GET": try: fetch_date = request.GET.get('date') #此时的日期是字符串 fetch_date = datetime.datetime.strptime(fetch_date, '%Y-%m-%d').date() #将日期字符串转换成时间对象,用于比较时间 if fetch_date < current_date: raise Exception('查询时间不能是以前的时间')
数据库查询、创建优化
针对跨表查询优化:select_related、prefetch_related
booking_list = models.Booking.objects.filter(booking_date=fetch_date).select_related('user', 'room').order_by( 'booking_time') #查询当前时间的预定信息,并按预定时间排序,且优化查询外键字段
批量创建:bulk_create
#增加记录 add_booking_list = [] for room_id, time_id_list in booking_info['add'].items(): for time_id in time_id_list: obj = models.Booking( user_id=request.session['user_info']['id'], room_id=room_id, booking_time=time_id, booking_date=booking_date ) add_booking_list.append(obj) models.Booking.objects.bulk_create(add_booking_list)
获取某一天的预定 current_date = "2017-11-11" current_date = datetime.datetime.strptime(current_date, '%Y-%m-%d').date() # 查询 # select * from booking models.booking.objects.filter(date=current_date) # 主动连表(join 连表查询有性能损耗)PS:大公司用空间换时间 # select * from booking left join user on user.id = booing.user_id ... models.booking.objects.filter(date=current_date).select_related('user','room') # 不连表 (in) # select * from booing # 获取booking中取到的所有 user_id_list # select * from user where id in user_id_list models.booking.objects.filter(date=current_date).prefetch_related('user','room') models.booking.objects.filter(date=current_date).select_related('user','room') booking_list = [ obj(id,user_id,room_id,time_id,date), obj(id,user_id,room_id,time_id,date), obj(id,user_id,room_id,time_id,date), obj(id,user_id,room_id,time_id,date), ] for item in booking_list: item.room_id, id.user.user
Q查询的用法
#删除记录 #因为我们需要将del字典里所记载的数据删除,每条需要删除的数据,在数据库匹配时要同时匹配user_id,booking_date,room_id,booking_time #四条个条件是AND关系,将每个纪律的查询都做出一个Q对象,然后放到另一个Q对象中,用OR连接,只有符合条件就删除 remove_booking = Q() for room_id, time_id_list in booking_info['del'].items(): for time_id in time_id_list: temp = Q() temp.connector = 'AND' temp.children.append(('user_id', request.session['user_info']['id'],)) temp.children.append(('booking_date', booking_date,)) temp.children.append(('room_id', room_id,)) temp.children.append(('booking_time', time_id,)) remove_booking.add(temp, 'OR') if remove_booking: #如果有需要删除的,才删除 models.Booking.objects.filter(remove_booking).delete()
booking_list = models.Booking.objects.filter(booking_date=fetch_date).select_related('user', 'room').order_by( 'booking_time') #查询当前时间的预定信息,并按预定时间排序,且优化查询外键字段 booking_dict = {} for item in booking_list: if item.room_id not in booking_dict: booking_dict[item.room_id] = {item.booking_time: {'name': item.user.name, 'id': item.user.id}} else: if item.booking_time not in booking_dict[item.room_id]: booking_dict[item.room_id][item.booking_time] = {'name': item.user.name, 'id': item.user.id} """ { room_id:{ time_id:{''}, time_id:{''}, time_id:{''}, } } """ room_list = models.MeetingRoom.objects.all() booking_info = [] for room in room_list: temp = [{'text': room.title, 'attrs': {'rid': room.id}, 'chosen': False}] for choice in models.Booking.time_choices: v = {'text': '', 'attrs': {'time-id': choice[0], 'room-id': room.id}, 'chosen': False} if room.id in booking_dict and choice[0] in booking_dict[room.id]: v['text'] = booking_dict[room.id][choice[0]]['name'] v['chosen'] = True if booking_dict[room.id][choice[0]]['id'] != request.session['user_info']['id']: v['attrs']['disable'] = 'true' temp.append(v) booking_info.append(temp) ret['data'] = booking_info
要学习这样转换数据的结构的方式

浙公网安备 33010602011771号