web
import json
import datetime
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from . import models
from django.forms import Form
from django.forms import fields
from django.forms import widgets
from django.db.models import Q
from django.db.utils import IntegrityError
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 auth_json(func):
def inner(request, *args, **kwargs):
user_info = request.session.get('user_info')
if not user_info:
return JsonResponse({
'status': False, 'msg': '用户未登录'})
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})
@auth
def index(request):
"""
会议室预定首页
:param request:
:return:
"""
time_choices = models.Booking.time_choices
return render(request, 'index.html', {
'time_choices': time_choices})
@auth_json
def booking(request):
"""
获取会议室预定情况以及预定会议室
:param request:
:param date:
:return:
"""
ret = {
'code': 1000, 'msg': None, 'data': None}
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('查询时间不能是以前的时间')
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
except Exception as e:
ret['code'] = 1001
ret['msg'] = str(e)
return JsonResponse(ret)
else:
try:
booking_date = request.POST.get('date')
booking_date = datetime.datetime.strptime(booking_date, '%Y-%m-%d').date()
if booking_date < current_date:
raise Exception('查询时间不能是以前的时间')
booking_info = json.loads(request.POST.get('data'))
for room_id, time_id_list in booking_info['add'].items():
if room_id not in booking_info['del']:
continue
for time_id in list(time_id_list):
if time_id in booking_info['del'][room_id]:
booking_info['del'][room_id].remove(time_id)
booking_info['add'][room_id].remove(time_id)
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)
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()
except IntegrityError as e:
ret['code'] = 1011
ret['msg'] = '会议室已被预定'
except Exception as e:
ret['code'] = 1012
ret['msg'] = '预定失败:%s' % str(e)
return JsonResponse(ret)
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)
def __str__(self):
return self.name
class MeetingRoom(models.Model):
title = models.CharField(verbose_name='会议室', max_length=32)
def __str__(self):
return self.title
class Booking(models.Model):
user = models.ForeignKey(to='UserInfo', verbose_name='用户', on_delete = models.CASCADE)
room = models.ForeignKey(to='MeetingRoom',verbose_name='会议室', on_delete = models.CASCADE)
booking_date = models.DateField(verbose_name='预定日期')
time_choices = (
(1, '08:00-09:00'),
(2, '09:00-10:00'),
(3, '10:00-10:00'),
(4, '11:00-12:00'),
(5, '12:00-13:00'),
(6, '13:00-14:00'),
(7, '14:00-15:00'),
(8, '15:00-16:00'),
(9, '16:00-17:00'),
(10, '17:00-18:00'),
(11, '18:00-19:00'),
(12, '19:00-20:00'),
(13, '20:00-21:00'),
)
booking_time = models.IntegerField(verbose_name='预定时间段', choices=time_choices)
class Meta:
unique_together = (
('booking_date', 'booking_time', 'room')
)
from django.contrib import admin
from web.models import UserInfo,MeetingRoom,Booking
class UserInfoAdmin(admin.ModelAdmin):
list_display = ('name', 'password')
class MeetingRoomAdmin(admin.ModelAdmin):
list_display = ['title']
class BookingRoomAdmin(admin.ModelAdmin):
list_display = ('booking_date', 'booking_time', 'room')
admin.site.register(UserInfo,UserInfoAdmin)
admin.site.register(MeetingRoom,MeetingRoomAdmin)
admin.site.register(Booking,BookingRoomAdmin)
templates
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'plugins/datetimepicker/bootstrap-datetimepicker.min.css' %}">
<style>
body {
font-size: 10px;
}
.shade {
position: fixed;
z-index: 1040;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #999;
filter: alpha(opacity=50);
-moz-opacity: 0.5;
opacity: 0.5;
}
.loading {
position: fixed;
z-index: 1050;
top: 40%;
left: 50%;
height: 32px;
width: 32px;
margin: 0 0 0 -16px;
background: url(/static/img/loading.gif);
}
table > tbody td {
height: 80px;
width: 80px;
text-align: center;
}
table > tbody td.chosen {
background-color: #F0FFF0;
}
table > tbody td.selected {
background-color: #EEE685;
}
</style>
</head>
<body>
<div class="container">
<h1>会议室预定</h1>
<div class="clearfix" style="padding: 10px 0;float: right">
<div style="float: left;color: red" id="errors"></div>
<div class='input-group' style="width: 230px;float:left;">
<input type='text' class="form-control" id='datetimepicker11' placeholder="请选择日期"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar">
</span>
</span>
</div>
<div style="padding: 0 5px;float: left">
<a id="save" href="#" class="btn btn-primary">保存</a>
</div>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th>会议室</th>
{% for choice in time_choices %}
<th>{
{ choice.1 }}</th>
{% endfor %}
</tr>
</thead>
<tbody id="tBody">
</tbody>
</table>
</div>
<div id='shade' class='shade hide'></div>
<div id='loading' class='loading hide'></div>
<script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
<script src="{% static 'js/jquery.cookie.js' %}"></script>
<script src="{% static 'plugins/bootstrap/js/bootstrap.min.js' %}"></script>
<script src="{% static 'plugins/datetimepicker/bootstrap-datetimepicker.min.js' %}"></script>
<script src="{% static 'plugins/datetimepicker/bootstrap-datetimepicker.zh-CN.js' %}"></script>
<script>
Date.prototype.Format = function (fmt) {
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;
};
SELECTED_ROOM = {
del: {
}, add: {
}};
CHOSEN_DATE = new Date().Format('yyyy-MM-dd');
$(function () {
initDatepicker();
initBookingInfo(new Date().Format('yyyy-MM-dd'));
bindTdEvent();
bindSaveEvent();
});
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
}
}
});
function initDatepicker() {
$('#datetimepicker11').datetimepicker({
minView: "month",
language: "zh-CN",
sideBySide: true,
format: 'yyyy-mm-dd',
bootcssVer: 3,
startDate: new Date()
}).on('changeDate', changeDate);
}
function changeDate(ev) {
CHOSEN_DATE = ev.date.Format('yyyy-MM-dd');
initBookingInfo(CHOSEN_DATE);
}
function initBookingInfo(date) {
SELECTED_ROOM = {
del: {
}, add: {
}};
$('#shade,#loading').removeClass('hide');
$.ajax({
url: '/booking/',
type: 'get',
data: {
date: date},
dataType: 'JSON',
success: function (arg) {
$('#shade,#loading').addClass('hide');
if (arg.code === 1000) {
$('#tBody').empty();
$.each(arg.data, function (i, item) {
var tr = document.createElement('tr');
$.each(item, function (j, row) {
var td = document.createElement('td');
$(td).text(row.text);
$.each(row.attrs, function (k, v) {
$(td).attr(k, v);
});
if (row.chosen) {
$(td).addClass('chosen');
}
$(tr).append(td)
});
$('#tBody').append(tr);
})
} else {
alert(arg.msg);
}
},
error: function () {
$('#shade,#loading').addClass('hide');
alert('请求异常');
}
})
}
function bindTdEvent() {
$('#tBody').on('click', 'td[time-id][disable!="true"]', function () {
var roomId = $(this).attr('room-id');
var timeId = $(this).attr('time-id');
if ($(this).hasClass('chosen')) {
$(this).removeClass('chosen').empty();
if (SELECTED_ROOM.del[roomId]) {
SELECTED_ROOM.del[roomId].push(timeId);
} else {
SELECTED_ROOM.del[roomId] = [timeId];
}
} else if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
var timeIndex = SELECTED_ROOM.add[roomId].indexOf(timeId);
if (timeIndex !== -1) {
SELECTED_ROOM.add[roomId].splice(timeIndex, 1);
}
} else {
$(this).addClass('selected');
if (SELECTED_ROOM.add[roomId]) {
SELECTED_ROOM.add[roomId].push(timeId);
} else {
SELECTED_ROOM.add[roomId] = [timeId];
}
}
})
}
function bindSaveEvent() {
$('#errors').text('');
$('#save').click(function () {
$('#shade,#loading').removeClass('hide');
$.ajax({
url: '/booking/',
type: 'POST',
data: {
date: CHOSEN_DATE, data: JSON.stringify(SELECTED_ROOM)},
dataType: 'JSON',
success: function (arg) {
$('#shade,#loading').addClass('hide');
if (arg.code === 1000) {
initBookingInfo(CHOSEN_DATE);
} else {
$('#errors').text(arg.msg);
}
}
});
});
}
</script>
</body>
</html>
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}">
</head>
<body>
<div style="width: 500px;margin: 50px auto;">
<form class="form-horizontal" method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label for="name" class="col-sm-2 control-label">用户名:</label>
<div class="col-sm-10">
{
{ form.name }}
{
{ form.errors.name.0 }}
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码:</label>
<div class="col-sm-10">
{
{ form.password }}
{
{ form.errors.password.0 }}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
{
{ form.rmb }} 一周免登录
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">登录</button>
</div>
</div>
</form>
<div>
<p>用户名:周杰伦 密码:123</p>
<p>用户名:吴彦祖 密码:123</p>
</div>
</div>
</body>
</html>