学了python的部分库和基本语法后,结合数据库操作,做一个简单的用户友好界面实现一个简单的酒店预订小系统。
tkinter的组件转换
tkinter按钮组件详解
Python连接数据库操作
数据库准备
在本地数据库新建一个hotel_data的数据库,建立四张表。
建表的查询语句如下:
/*
Navicat Premium Data Transfer
Source Server : mysql
Source Server Type : MySQL
Source Server Version : 80012
Source Host : localhost:3306
Source Schema : hotel_data
Target Server Type : MySQL
Target Server Version : 80012
File Encoding : 65001
Date: 22/11/2018 16:05:09
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for hotel
-- ----------------------------
DROP TABLE IF EXISTS `hotel`;
CREATE TABLE `hotel` (
`hotel_id` int(11) NOT NULL,
`hotel_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`stars` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`hotel_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of hotel
-- ----------------------------
INSERT INTO `hotel` VALUES (1, '惠民旅馆', 5);
INSERT INTO `hotel` VALUES (2, '风景旅馆', 4);
INSERT INTO `hotel` VALUES (3, '商务旅馆', 4);
-- ----------------------------
-- Table structure for order
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`order_id` int(11) NOT NULL COMMENT 'joer',
`room_id` int(11) NULL DEFAULT NULL,
`start_date` date NULL DEFAULT NULL,
`leave_date` date NULL DEFAULT NULL,
`amount` int(11) NULL DEFAULT NULL,
`payment` int(11) NULL DEFAULT NULL,
`create_date` date NULL DEFAULT NULL,
PRIMARY KEY (`order_id`) USING BTREE,
INDEX `room_order_id`(`room_id`) USING BTREE,
CONSTRAINT `room_order_id` FOREIGN KEY (`room_id`) REFERENCES `room_type` (`room_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of order
-- ----------------------------
INSERT INTO `order` VALUES (0, 6, '2018-11-14', '2018-11-15', 4, 2000, '2018-11-01');
INSERT INTO `order` VALUES (1, 5, '2018-11-14', '2018-11-16', 2, 2100, '2018-11-01');
INSERT INTO `order` VALUES (2, 1, '2018-11-14', '2018-11-14', 5, 2500, '2018-11-01');
INSERT INTO `order` VALUES (3, 8, '2018-11-14', '2018-11-16', 2, 1296, '2018-11-01');
INSERT INTO `order` VALUES (4, 4, '2018-11-14', '2018-11-16', 2, 2400, '2018-11-01');
-- ----------------------------
-- Table structure for room_info
-- ----------------------------
DROP TABLE IF EXISTS `room_info`;
CREATE TABLE `room_info` (
`info_id` int(11) NOT NULL,
`date` date NULL DEFAULT NULL,
`price` decimal(10, 2) NULL DEFAULT NULL,
`remain` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`room_id` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`info_id`) USING BTREE,
INDEX `room_info_key`(`room_id`) USING BTREE,
CONSTRAINT `room_info_key` FOREIGN KEY (`room_id`) REFERENCES `room_type` (`room_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of room_info
-- ----------------------------
INSERT INTO `room_info` VALUES (1, '2018-11-14', 500.00, '5', 1);
INSERT INTO `room_info` VALUES (2, '2018-11-15', 500.00, '4', 1);
INSERT INTO `room_info` VALUES (3, '2018-11-16', 600.00, '6', 1);
INSERT INTO `room_info` VALUES (4, '2018-11-14', 300.00, '6', 2);
INSERT INTO `room_info` VALUES (5, '2018-11-15', 300.00, '5', 2);
INSERT INTO `room_info` VALUES (6, '2018-11-16', 400.00, '5', 2);
INSERT INTO `room_info` VALUES (7, '2018-11-14', 200.00, '4', 3);
INSERT INTO `room_info` VALUES (8, '2018-11-15', 200.00, '3', 3);
INSERT INTO `room_info` VALUES (9, '2018-11-16', 300.00, '4', 3);
INSERT INTO `room_info` VALUES (10, '2018-11-14', 450.00, '5', 4);
INSERT INTO `room_info` VALUES (11, '2018-11-15', 300.00, '5', 4);
INSERT INTO `room_info` VALUES (12, '2018-11-16', 450.00, '5', 4);
INSERT INTO `room_info` VALUES (13, '2018-11-14', 400.00, '2', 5);
INSERT INTO `room_info` VALUES (14, '2018-11-15', 250.00, '2', 5);
INSERT INTO `room_info` VALUES (15, '2018-11-16', 400.00, '2', 5);
INSERT INTO `room_info` VALUES (16, '2018-11-14', 300.00, '1', 6);
INSERT INTO `room_info` VALUES (17, '2018-11-15', 200.00, '1', 6);
INSERT INTO `room_info` VALUES (18, '2018-11-16', 300.00, '5', 6);
INSERT INTO `room_info` VALUES (19, '2018-11-14', 300.00, '2', 7);
INSERT INTO `room_info` VALUES (20, '2018-11-15', 250.00, '3', 7);
INSERT INTO `room_info` VALUES (21, '2018-11-16', 300.00, '8', 7);
INSERT INTO `room_info` VALUES (22, '2018-11-14', 250.00, '1', 8);
INSERT INTO `room_info` VALUES (23, '2018-11-15', 200.00, '1', 8);
INSERT INTO `room_info` VALUES (24, '2018-11-16', 200.00, '5', 8);
INSERT INTO `room_info` VALUES (25, '2018-11-14', 200.00, '2', 9);
INSERT INTO `room_info` VALUES (26, '2018-11-15', 150.00, '4', 9);
INSERT INTO `room_info` VALUES (27, '2018-11-16', 150.00, '4', 9);
-- ----------------------------
-- Table structure for room_type
-- ----------------------------
DROP TABLE IF EXISTS `room_type`;
CREATE TABLE `room_type` (
`room_id` int(11) NOT NULL,
`room_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`hotel_id` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`room_id`) USING BTREE,
INDEX `hotel_room_key`(`hotel_id`) USING BTREE,
CONSTRAINT `hotel_room_key` FOREIGN KEY (`hotel_id`) REFERENCES `hotel` (`hotel_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of room_type
-- ----------------------------
INSERT INTO `room_type` VALUES (1, '大床房', 1);
INSERT INTO `room_type` VALUES (2, '双人房', 1);
INSERT INTO `room_type` VALUES (3, '三人房', 1);
INSERT INTO `room_type` VALUES (4, '海景房', 2);
INSERT INTO `room_type` VALUES (5, '园景房', 2);
INSERT INTO `room_type` VALUES (6, '山景房', 2);
INSERT INTO `room_type` VALUES (7, '总统套房', 3);
INSERT INTO `room_type` VALUES (8, '豪华套房', 3);
INSERT INTO `room_type` VALUES (9, '33号房', 3);
SET FOREIGN_KEY_CHECKS = 1;
drop table if EXISTS `user_order`;
CREATE TABLE `user_order` (
`user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci,
`hotel` varchar(255) NULL DEFAULT NULL,
`room_name` varchar(255) NULL DEFAULT NULL,
`nums` int(10) NULL DEFAULT NULL,
`start_date` varchar(255) NULL DEFAULT NULL,
`end_date` varchar(255) NULL DEFAULT NULL,
`price` INT(10) NULL DEFAULT NULL,
PRIMARY KEY (`user`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
drop table if EXISTS `user_inf`;
CREATE TABLE `user_inf` (
`user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci,
`passwd` varchar(255) NULL DEFAULT NULL,
`ID` varchar(255) NULL DEFAULT NULL,
`Tel` varchar(255) NULL DEFAULT NULL,
PRIMARY KEY (`user`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
建好后四张表如下:
系统:WIN10
语言:Python 2.7
IDLE: PyCharm
调用包:
*tkinter(自带GUI包)
*pandas(存取csv文件)
*MySQLDb(数据库操作)
*PIL库(图像处理)
*time (用于延时处理)
测试由命令行窗口显示,若测试与系统中显示信息一致,则通过验证。
用于测试的账号(预存在数据库user_inf表中,你也可以自己设置):
做好的GUI界面如下:
测试窗口结果:
用户输入是:
2018-11-14 2018-11-16 0 1000 1
满足条件的有
hotel_name stars room_name remain price
0 惠民旅馆 5 大床房 5 500.0
1 惠民旅馆 5 大床房 4 500.0
2 惠民旅馆 5 大床房 6 600.0
3 惠民旅馆 5 双人房 6 300.0
4 惠民旅馆 5 双人房 5 300.0
5 惠民旅馆 5 双人房 5 400.0
6 惠民旅馆 5 三人房 4 200.0
7 惠民旅馆 5 三人房 3 200.0
8 惠民旅馆 5 三人房 4 300.0
9 风景旅馆 4 海景房 5 450.0
10 风景旅馆 4 海景房 2 300.0
11 风景旅馆 4 海景房 2 450.0
12 风景旅馆 4 园景房 2 400.0
13 风景旅馆 4 园景房 2 250.0
14 风景旅馆 4 园景房 2 400.0
15 风景旅馆 4 山景房 1 300.0
16 风景旅馆 4 山景房 1 200.0
17 风景旅馆 4 山景房 5 300.0
18 商务旅馆 4 总统套房 2 300.0
19 商务旅馆 4 总统套房 3 250.0
20 商务旅馆 4 总统套房 8 300.0
21 商务旅馆 4 豪华套房 1 250.0
22 商务旅馆 4 豪华套房 1 200.0
23 商务旅馆 4 豪华套房 5 200.0
24 商务旅馆 4 33号房 2 200.0
25 商务旅馆 4 33号房 4 150.0
26 商务旅馆 4 33号房 4 150.0
['lk', 'lk', '2018-11-14', '2018-11-16', 1]
[u'\u603b\u7edf\u5957\u623f', 8, 300.0]
select * from `user_order` where user='lk'
查询成功
用户的最终选择为:
(u'lk', u'UNSHOWED', u'UNSHOWED', 1L, u'2018-11-14', u'2018-11-16', 200L)
之前的用户测试的时候预定过该房间,所以预定失败。现在切换用户进行新一轮的测试。
点击退出切换到下一个用户。
测试窗口:
用户输入是:
2018-11-14 2018-11-16 0 1000 1
满足条件的有
hotel_name stars room_name remain price
21 商务旅馆 4 豪华套房 1 250.0
22 商务旅馆 4 豪华套房 1 200.0
23 商务旅馆 4 豪华套房 5 200.0
['psr', 'psr', '2018-11-14', '2018-11-16', 1]
[u'\u8c6a\u534e\u5957\u623f', 1, 250.0]
插入数据库的信息是:
INSERT INTO `user_order`(`user`,`hotel`,`room_name`,`nums`,`start_date`,`end_date`,`price`)VALUES('psr','UNSHOWED','UNSHOWED','1','2018-11-14','2018-11-16','250')
预定成功
select * from `user_order` where user='psr'
查询成功
用户的最终选择为:
(u'psr', u'UNSHOWED', u'UNSHOWED', 1L, u'2018-11-14', u'2018-11-16', 250L)
全部代码包含详细注释:
# -author:LK12 time:2018/11/26
# -*- coding:utf-8 -*-
import tkinter as tk
from PIL import ImageTk,Image
import time
import tkinter.font as tkFont
import MySQLdb
import pandas as pd
from tkinter import ttk
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
### 设置框架大小等性质,这样就不用每次都重新设置
## 主界面,登陆界面
class MainFrame(tk.Tk):
def __init__(self,title):
tk.Tk.__init__(self)
self.title(title)
self.iconbitmap('hotel1.ico')
self.geometry('280x470+500+100')
self.attributes('-alpha', 0.92)
## 其他界面
class OtherFrame(tk.Toplevel):
def __init__(self, title):
tk.Toplevel.__init__(self)
self.title(title)
self.iconbitmap('hotel1.ico')
self.geometry('280x470+500+100')
self.attributes('-alpha', 0.92)
class user_login(object):
def __init__(self, root):
self.root = root
# 登陆提示信息设置为可变,用于提醒用户是否登陆成功
self.var1 = tk.StringVar()
self.var1.set('Hotel Order System')
# 连接数据库
self.conn = MySQLdb.Connection(
host='localhost',
port=3306,
user='root',
passwd='root',
db='hotel_data',
charset='utf8'
)
# 获取管理员权限可见的账户信息,提取出账户和密码存入字典便于验证
self.cursor = self.conn.cursor()
self.cursor.execute('select user,passwd from user_inf')
login_inf = self.cursor.fetchall()
user_inf = [str(ii[0]) for ii in login_inf]
passwd_inf = [str(ii[1]) for ii in login_inf]
self.dict_inf = dict(zip(user_inf, passwd_inf))
# 获取三个表自然连接即所有信息,为了转换格式将其存入csv文件再提取出来,编码变为gb2312
sql1 = 'select * from (room_type NATURAL JOIN hotel)NATURAL JOIN room_info'
self.cursor.execute(sql1)
hotel_inf = self.cursor.fetchall()
hotel_inf = pd.DataFrame(list(hotel_inf), columns=['room_id', 'hotel_id', 'room_name',
'hotel_name', 'stars', 'info_id',
'date', 'price', 'remain'])
hotel_inf = hotel_inf.drop(['info_id'], axis=1)
hotel_inf.to_csv('12.csv', encoding='gb2312')
self.hotel_inf = pd.read_csv('12.csv', encoding='gb2312')
frame1 = tk.Frame() #框架一 标志图标
frame2 = tk.Frame() #框架二 用户密码
frame3 = tk.Frame() #框架三 忘记密码
frame4 = tk.Frame() #框架四 注释
# 读取图片添加到登陆验证页,增加美感
pic = Image.open('hotel.jpg')
# 设置读取的图片为全局变量,在class外部才能正确显示
global img
img = ImageTk.PhotoImage(pic)
# 登陆验证页面的框架组织
tk.Label(frame1,
textvariable=self.var1,
compound=tk.CENTER,
fg='green',
bg='red',
font=('Fixdsys', 10),
width=140,
justify=tk.CENTER,
height=10,
bd=80,
image=img
).grid(row=5, padx=10, pady=5)
tk.Label(frame2, text='用户名',bd=4).grid(row=0)
tk.Label(frame2, text='密码',bd=4).grid(row=1)
self.e1 = tk.Entry(frame2)
self.e1.grid(row=0, column=1, padx=10, pady=5)
self.e2 = tk.Entry(frame2,show='*')
self.e2.grid(row=1, column=1, padx=10, pady=5)
self.e1.insert(0, 'lk')
self.e2.insert(0, 'lk')
b1 = tk.Button(frame2,text='登陆', command=self.login, width=10,fg='white',bg='blue')
b1.grid(row=3, column=0, sticky=tk.W, padx=10, pady=5)
b2 = tk.Button(frame2,text='免费注册', command=self._register, width=10,fg='blue',highlightcolor='blue')
b2.grid(row=3, column=1, sticky=tk.E, padx=10, pady=5)
tk.Button(frame3, text='忘记密码',bd=5, command=self.forget_pwd).pack()
l4 = tk.Label(frame4,
text='*这是一个简单的酒店预定小系统\n\n'
'*用于测试的账号和密码:lk/lk\n\n'
'*可以自己注册,信息将写入数据库\n\n'
'*该小系统由python自带tkinter包构建\n\n'
'*开发环境:windows10 Python 2.7\n'
' --All rights reserved by LK',
justify=tk.LEFT,
bg='gray',
fg='purple',
width=130,
highlightcolor='purple',
font=tkFont.Font(family='楷体',size=9, underline=0))
l4.pack()
frame1.pack(side=tk.TOP)
frame2.pack()
frame3.pack()
frame4.pack(side=tk.BOTTOM)
### 登陆成功后普通查询界面
def login(self):
global top_login
if self.e1.get() in self.dict_inf.keys():
if self.e2.get() == self.dict_inf[self.e1.get()]:
self.root.withdraw()
top_login = OtherFrame('登陆成功,欢迎您:%s' % (self.e1.get()))
f0 = tk.Frame(top_login)
f1 = tk.Frame(top_login, bg='gray')
f2 = tk.Frame(top_login)
f0.grid(row=0)
f1.grid(row=1)
f2.grid(row=2)
## 跳转至查询界面
def search_hotel():
top_login.withdraw()
self.login()
## 跳转至订单界面
def watch_order():
top_login.withdraw()
self.order()
select_b1 = tk.Button(f0,text='酒店查询',fg='white',bg='blue',width=17,command=search_hotel)
select_b1.pack(side=tk.LEFT)
select_b2 = tk.Button(f0,text='订单查询',fg='white',bg='blue',width=17,command=watch_order)
select_b2.pack(side=tk.RIGHT)
## 日期选择
l1 = tk.Label(f1,text='日期选择')
l1.grid(row=0)
# 入住日期滑动选择
start_date_var = tk.StringVar()
ttk1 = ttk.Combobox(f1,width=12,textvariable=start_date_var,
values=['2018-11-14','2018-11-15','2018-11-16'],state='readonly')
ttk1.current(0)
ttk1.set('入住日期')
ttk1.grid(row=1, column=0)
# 过渡标签
l12 = tk.Label(f1, text='>>>')
l12.grid(row=1, column=2)
# 离开日期滑动选择
end_day_var = tk.StringVar()
ttk2 = ttk.Combobox(f1, width=12, textvariable=end_day_var,
values=['2018-11-14', '2018-11-15', '2018-11-16'], state='readonly')
ttk2.current(0)
ttk2.set('离开日期')
ttk2.grid(row=1, column=3)
## 价格区间选择
l2 = tk.Label(f1, text='价格选择')
l2.grid(row=2)
# 最低价格
low_price_var = tk.StringVar()
ttk3 = ttk.Combobox(f1,width=12,textvariable=low_price_var,
values=['0','200','400','500'],state='readonly')
ttk3.current(0)
ttk3.set('最低价格')
ttk3.grid(row=3, column=0)
# >>>标签
tk.Label(f1, text='>>>').grid(row=3, column=2)
# 最高价格
high_price_var = tk.StringVar()
ttk4 = ttk.Combobox(f1, width=12, textvariable=high_price_var,
values=['500', '600', '700', '1000'], state='readonly')
ttk4.current(0)
ttk4.set('最高价格')
ttk4.grid(row=3, column=3)
## 房型选择
tk.Label(f1, text='房型选择').grid(row=4, column=0)
tk.Label(f1, text='预定房数').grid(row=4, column=3)
room_name_var = tk.StringVar()
ttk5 = ttk.Combobox(f1,width=12,textvariable=room_name_var,values=['大床房','双人房','三人房','海景房','园景房'
,'山景房','总统套房','豪华套房','33号房'])
ttk5.current(0)
ttk5.set('默认都行')
ttk5.grid(row=5,column=0)
## 预定数选择
remain_var = tk.StringVar()
ttk6 = ttk.Combobox(f1, width=12, textvariable=remain_var, values=['1', '2', '3', '4', '5'
, '6', '7', '8', '9'])
ttk6.current(0)
ttk6.grid(row=5, column=3)
## 获取用户输入并进行选择
def get_hotel_inf():
global start_date,end_date,remain,selected
start_date = ttk1.get()
end_date = ttk2.get()
low_price = int(ttk3.get())
high_price = int(ttk4.get())
room_name = ttk5.get()
remain = int(ttk6.get())
print '用户输入是:'
print start_date,end_date,low_price,high_price,remain
try:
if room_name == u'默认都行':
selected = self.hotel_inf[(self.hotel_inf['date']>=start_date)
&(self.hotel_inf['date']<=end_date)
&(self.hotel_inf['price']>=low_price)
&(self.hotel_inf['price']<=high_price)
&(self.hotel_inf['remain']>=remain)]
else:
selected = self.hotel_inf[(self.hotel_inf['date'] >= start_date)
& (self.hotel_inf['date'] <= end_date)
& (self.hotel_inf['price'] >= low_price)
& (self.hotel_inf['price'] <= high_price)
& (self.hotel_inf['remain'] >= remain)
& (self.hotel_inf['room_name'] == room_name)]
selected = selected[['hotel_name','stars','room_name','remain','price']]
print '满足条件的有'
print selected
except MySQLdb.Error:
self.conn.rollback()
selected = [-1,-1]
hotel = selected.drop_duplicates(subset='hotel_name',keep='first')
hotel = hotel.reset_index(drop=True)
hotel_name = hotel['hotel_name']
tk.Label(f2,
text='>>共搜到%d个酒店%d间房型满足您的条件\n点击酒店查看具体信息'%(len(hotel_name),len(selected)),
justify=tk.LEFT).grid(column=0)
## 查询结果显示
def callback(hotel_index):
Inf = selected[selected['hotel_name'] == hotel_name[hotel_index]]
v3 = tk.IntVar()
v3.set(1)
Inf = Inf.reset_index(drop=True)
Inf = Inf[['room_name', 'remain', 'price']]
Inf.columns = ['房型', '剩余', '单价']
bg_colors = ['green', 'yellow', 'blue']
fg_colors = ['white', 'red', 'white']
## 当用户选择了具体的房间后,进入确认预定界面,显示该用户信息和酒店信息
def get_room():
ensure_inf = OtherFrame('确认预定?')
global home_price
home_price = Inf.ix[v3.get()].tolist()
print [self.e1.get(), self.e2.get(), start_date, end_date, remain]
print home_price
def write_to_sql():
try:
# 插入user/hotel/room_name/nums/sday/eday/price
sql_insert_order = "INSERT INTO " \
"`user_order`(`user`,`hotel`,`room_name`,`nums`,`start_date`,`end_date`,`price`)" \
"VALUES('%s','%s','%s','%d','%s','%s','%d')"\
%(self.e1.get(),'UNSHOWED','UNSHOWED',int(remain),start_date,end_date,int(home_price[2]))
self.cursor.execute(sql_insert_order)
self.conn.commit()
tk.Label(ensure_inf,text='预定成功').pack()
tk.Button(ensure_inf,text='查看订单',command=watch_order).pack(side=tk.LEFT)
tk.Button(ensure_inf,text='退出',command=self.leave).pack(side=tk.RIGHT)
print '插入数据库的信息是:'
print sql_insert_order
print '预定成功'
except MySQLdb.Error as e:
tk.Label(ensure_inf, justify=tk.LEFT,text='预定失败\n'
'原因:\n'+'用户已经订过了').pack()
tk.Button(ensure_inf, text='退出', command=self.leave).pack(side=tk.LEFT)
tk.Button(ensure_inf, text='查看订单', command=watch_order).pack(side=tk.RIGHT)
self.conn.rollback()
tk.Label(ensure_inf,text= '请确认你的预定操作\n用户:%s\n起始日期:%s\n'
'结束日期:%s\n'
'预定房数:%d\n'
'单价:%d\n' %(self.e1.get(),start_date,end_date,remain,home_price[2]),
bd=20,
font=10).pack()
tk.Button(ensure_inf,text='确认',command=write_to_sql).pack()
ensure_inf.mainloop()
detail_inf = OtherFrame('❤请选择❤')
group = tk.LabelFrame(detail_inf,
text='》》点击预定《《',
padx=10,
pady=10,
width=140,
height=10,
)
group.pack()
for jj in range(len(Inf)):
tk.Radiobutton(group,
text=Inf.ix[jj],
variable=v3,
value=jj,
indicatoron=0,
bg=bg_colors[jj],
fg=fg_colors[jj],
activebackground='red',
justify=tk.LEFT,
command=get_room).pack()
tk.Label(detail_inf,textvariable=v3).pack()
detail_inf.mainloop()
for ii in range(len(hotel_name)):
callback0 = lambda:callback(ii)
tk.Label(f2, text='⭐' * hotel.stars[ii], fg='red',font=5).grid()
tk.Button(f2,
text=hotel_name[ii],
compound=tk.CENTER,
image=img,
bd=10,
height=30,width=150,
font=('幼圆',20),
command=callback0).grid()
self.conn.rollback()
tk.Button(f1, text='搜索', command=get_hotel_inf).grid(row=7, columns=2)
tk.Button(f1,text='重新搜索',command=self.login).grid(row=7,column=3)
tk.Button(f1,text='高级筛选',command=self.customed_select).grid(row=7,columns=4)
top_login.mainloop()
else:
self.var1.set('密码错误')
else:
self.var1.set('用户名不存在,欢迎注册')
### 用户自定义高级筛选,这些查询就比较变态
def customed_select(self):
# 点击第一种变态查询的响应
def select1():
def select1_inf():
if select1_ttk.get() == '不限':
sql_select1 = "select DISTINCT hotel_name,room_name FROM (room_type NATURAL JOIN hotel)"
else:
sql_select1 = "select DISTINCT hotel_name,room_name FROM (room_type NATURAL JOIN hotel)" \
" where hotel_name='{}'".format(select1_ttk.get())
self.cursor.execute(sql_select1)
cs2_inf = self.cursor.fetchall()
cs2_l1 = tk.Listbox(select1_lf2,width=30)
for ii in cs2_inf:
cs2_l1.insert(tk.END,ii)
cs2_l1.pack()
cs2 = OtherFrame('酒店:房型')
tk.Label(cs2, text='查询酒店房型列表,返回酒店名,房型名').pack()
select1_lf1 = tk.LabelFrame(cs2, text='选择酒店')
select1_lf1.pack()
select1_var = tk.StringVar()
select1_ttk = ttk.Combobox(select1_lf1, textvariable=select1_var, state='readonly',
values=['惠民旅馆', '风景旅馆', '商务旅馆'])
select1_ttk.current(0)
select1_ttk.set('不限')
select1_ttk.pack(side=tk.LEFT)
tk.Button(select1_lf1, text='查询', command=select1_inf).pack(side=tk.LEFT)
tk.Button(select1_lf1, text='重置', command=select1).pack(side=tk.RIGHT)
tk.Button(cs2, text='返回', command=self.customed_select).pack(side=tk.LEFT)
tk.Button(cs2, text='退出', command=self.leave).pack(side=tk.RIGHT)
select1_lf2 = tk.LabelFrame(cs2, text='查询结果')
select1_lf2.pack()
cs2.mainloop()
# 点击第二种变态查询的响应
def select2():
# 用户选择日期后的信息显示响应
def select2_inf():
sql_select2 = "SELECT hotel_name,avg(price) as avg_price,date " \
"from (room_type NATURAL JOIN hotel)NATURAL JOIN room_info " \
"where date='{}' " \
"GROUP BY hotel_id " \
"ORDER BY avg_price".format(select2_ttk.get())
self.cursor.execute(sql_select2)
cs3_inf = self.cursor.fetchall()
cs3_l1 = tk.Listbox(select2_lf2,width=30)
for ii in cs3_inf:
cs3_l1.insert(tk.END, ii)
cs3_l1.insert(0,['Hotel','Date','Avg_Price'])
cs3_l1.pack()
cs3 = OtherFrame('酒店-日期-均价')
tk.Label(cs3,text='查询酒店某天所有房型的平均价格并从低\n到高排序,返回酒店名,日期,平均价格').pack()
select2_lf1 = tk.LabelFrame(cs3,text='选择日期')
select2_lf1.pack()
select2_ttk = ttk.Combobox(select2_lf1, values=['2018-11-14','2018-11-15','2018-11-16'],state='readonly')
select2_ttk.current(0)
select2_ttk.pack(side=tk.LEFT)
tk.Button(select2_lf1, text='查询', command=select2_inf).pack(side=tk.LEFT)
tk.Button(select2_lf1, text='重置', command=select2).pack(side=tk.RIGHT)
tk.Button(cs3, text='返回', command=self.customed_select).pack(side=tk.LEFT)
tk.Button(cs3, text='退出', command=self.leave).pack(side=tk.RIGHT)
select2_lf2 = tk.LabelFrame(cs3, text='查询结果')
select2_lf2.pack()
cs3.mainloop()
# 点击第三种变态查询的响应
def select3():
def select3_inf():
sql_select3 = "SELECT hotel_name,room_name,avg(price) as avg_price " \
"from((SELECT *,count(room_name) from (room_type NATURAL JOIN hotel)NATURAL JOIN room_info " \
"where date>='{0}' AND date<='{1}' AND remain>=4 " \
"GROUP BY room_name " \
"HAVING count(room_name)={2})as M) " \
"GROUP BY room_name " \
"ORDER BY avg_price".format(select3_ttk1.get(),select3_ttk2.get(),int(select3_ttk3.get()))
print sql_select3
self.cursor.execute(sql_select3)
cs4_inf = self.cursor.fetchall()
cs4_l1 = tk.Listbox(select3_lf2, width=30)
for ii in cs4_inf:
cs4_l1.insert(tk.END,ii)
cs4_l1.pack()
cs4 = OtherFrame('酒店—房型-剩余数')
tk.Label(cs4, text='指定时间范围和要型预定房的\n房间数量,查询满足条件(时间,剩余\n房间数量)的房型及其平均价格,\n'
'并按房型平均价格从低到高进行排序。\n查询结果应包含酒店,房型及平均价格信息',
justify=tk.LEFT).pack()
select3_lf1 = tk.LabelFrame(cs4, text='请选择')
select3_lf1.pack()
tk.Label(select3_lf1,text='起始日期').pack()
select3_ttk1 = ttk.Combobox(select3_lf1, values=['2018-11-14', '2018-11-15', '2018-11-16'],
state='readonly')
select3_ttk1.current(0)
select3_ttk1.pack()
tk.Label(select3_lf1,text='结束日期').pack()
select3_ttk2 = ttk.Combobox(select3_lf1, values=['2018-11-14', '2018-11-15', '2018-11-16'],state='readonly')
select3_ttk2.current(0)
select3_ttk2.pack()
tk.Label(select3_lf1, text='预定数').pack()
select3_ttk3 = ttk.Combobox(select3_lf1, values=['1', '2', '3','4','5'],
state='readonly')
select3_ttk3.current(0)
select3_ttk3.pack()
tk.Button(cs4,text='查询',command=select3_inf).pack()
tk.Button(cs4, text='重置', command=select3).pack()
tk.Button(cs4,text='退出',command=self.leave).pack(side=tk.RIGHT)
tk.Button(cs4,text='返回',command=self.customed_select).pack(side=tk.LEFT)
select3_lf2 = tk.LabelFrame(cs4, text='查询结果')
select3_lf2.pack()
cs4.mainloop()
# 点击第四种变态查询的响应
def select4():
def select4_inf():
sql_select4 = "SELECT hotel_name,'{0}' as date,room_name,sum(amount) as sum_amount " \
"FROM (`order` NATURAL join room_type)NATURAL JOIN hotel " \
"WHERE start_date<='{1}' and leave_date>='{2}'" \
"GROUP BY room_name".format(select4_ttk.get(),select4_ttk.get(),select4_ttk.get())
self.cursor.execute(sql_select4)
cs5_inf = self.cursor.fetchall()
cs5_l1 = tk.Listbox(select4_lf2,width=30)
for ii in cs5_inf:
cs5_l1.insert(0, ii)
cs5_l1.pack()
cs5 = OtherFrame('酒店—房型-剩余数')
tk.Label(cs5, text='查询指定日期,各酒店,各房型的预定数量',
justify=tk.LEFT).pack()
select4_lf1 = tk.LabelFrame(cs5, text='日期选择')
select4_lf1.pack()
select4_ttk = ttk.Combobox(select4_lf1,values=['2018-11-14','2018-11-15','2018-11-16'],state='readonly')
select4_ttk.current(0)
select4_ttk.pack()
tk.Button(select4_lf1,text='查询', command=select4_inf).pack(side=tk.LEFT)
tk.Button(select4_lf1,text='重置',command=select4).pack(side=tk.RIGHT)
tk.Button(cs5,text='退出',command=self.leave).pack(side=tk.RIGHT)
tk.Button(cs5,text='返回',command=self.customed_select).pack(side=tk.LEFT)
select4_lf2 = tk.LabelFrame(cs5, text='查询结果')
select4_lf2.pack()
cs5.mainloop()
def select5():
def select5_inf():
pass
pass
## 集中变态查询的选择界面框架组织
cs1 = OtherFrame('高级查询')
lf1 = tk.LabelFrame(cs1,text='>>请选择你想进行的具体查询,点击进入<<')
lf1.pack()
tk.Button(lf1,text = '查询酒店房型列表,返回酒店名,房型名',
command=select1,bd=4,width=35,bg='blue',fg='white',activebackground='red').pack()
tk.Label(lf1,text='').pack()
tk.Button(lf1, text='查询酒店某天所有房型的平均价格并从低\n到高排序,返回酒店名,日期,平均价格',
justify=tk.LEFT,
command=select2,bd=4,width=35,bg='blue',fg='white',activebackground='red').pack()
tk.Label(lf1, text='').pack()
tk.Button(lf1, text='指定时间范围和要型预定房的\n房间数量,查询满足条件(时间,剩余\n房间数量)的房型及其平均价格,\n'
'并按房型平均价格从低到高进行排序。\n查询结果应包含酒店,房型及平均价格信息',
justify=tk.LEFT,
command=select3,bd=4,width=35,bg='blue',fg='white',activebackground='red').pack()
tk.Label(lf1, text='').pack()
tk.Button(lf1, text='查询指定日期,各酒店,各房型的预定数量',
command=select4,bd=4,width=35,bg='blue',fg='white',activebackground='red').pack()
tk.Label(lf1, text='').pack()
tk.Button(lf1, text='Q6那种变态筛选',
command=select4, bd=4, width=35, bg='blue', fg='white', activebackground='red').pack()
tk.Label(lf1, text='').pack()
tk.Button(lf1,text='返回普通筛选',command=self.login,bg='pink').pack(side=tk.LEFT)
tk.Button(lf1, text='退出', command=self.leave,bg='red').pack(side=tk.RIGHT)
cs1.mainloop()
## 根据用户选择的变态查询,访问数据库查询函数
def select_operation(self,select_sql):
try:
self.cursor.execute(select_sql)
Inf = self.cursor.fetchall()
print '查询成功,信息如下:'
for each_line in Inf:
print each_line
except MySQLdb.Error as e:
print 'select wrong'+str(e)
self.conn.rollback()
Inf = 0
return Inf
def other_operation(self,sql_insert):
try:
self.cursor.execute(sql_insert)
n = self.cursor.rowcount
self.conn.commit()
print '成功,共更新%d条记录'%int(n)
except MySQLdb.Error as e:
print 'insert wrong'+str(e)
self.conn.rollback()
## 登陆验证界面和主查询界面的转换
def close_open(self,close_window,open_window):
close_window.withdraw()
open_window.update()
open_window.deiconify()
## 定义用户订单的界面
def order(self):
def search_hotel():
top_order.withdraw()
self.login()
def watch_order():
top_login.withdraw()
top_login.destroy()
self.order()
top_order = tk.Toplevel()
top_order.iconbitmap('hotel1.ico')
top_order.geometry('300x450+500+100')
top_order.title('登陆成功,欢迎您:%s' % (self.e1.get()))
f0 = tk.Frame(top_order)
f1 = tk.Frame(top_order, bg='gray')
select_b1 = tk.Button(f0, text='酒店查询', fg='white', bg='blue', width=17,command=search_hotel)
select_b1.pack(side=tk.LEFT)
select_b2 = tk.Button(f0, text='订单查询', fg='white', bg='blue', width=17,command=watch_order)
select_b2.pack(side=tk.RIGHT)
try:
self.conn.rollback()
sql_sel = "select * from `user_order` where user='%s' "%self.e1.get()
self.cursor.execute(sql_sel)
search_inf = self.cursor.fetchone()
print '查询成功'
except MySQLdb.Error as e:
search_inf = []
print '查询失败'
print e
print '用户的最终选择为:'
print search_inf
try:
tk.Label(f1,text='用户名',fg='red').grid(row=0,column=0)
tk.Label(f1,text=self.e1.get(),fg='blue').grid(row=0,column=3)
tk.Label(f1, text='酒店',fg='red').grid(row=1,column=0)
hotel_sel = selected['hotel_name'].tolist()
tk.Label(f1, text=hotel_sel[0],fg='blue').grid(row=1,column=3)
tk.Label(f1, text='房型',fg='red').grid(row=2,column=0)
tk.Label(f1, text=home_price[0],fg='blue').grid(row=2,column=3)
tk.Label(f1, text='预定数量',fg='red').grid(row=3,column=0)
tk.Label(f1, text=remain,fg='blue').grid(row=3,column=3)
tk.Label(f1, text='入住时间',fg='red').grid(row=4,column=0)
tk.Label(f1, text=start_date,fg='blue').grid(row=4,column=3)
tk.Label(f1, text='退房时间',fg='red').grid(row=5,column=0)
tk.Label(f1, text=end_date,fg='blue').grid(row=5,column=3)
tk.Label(f1, text='单价',fg='red').grid(row=6,column=0)
tk.Label(f1, text=home_price[2],fg='blue').grid(row=6,column=3)
tk.Button(f1, text='退出', command=self.leave).grid(row=9,column=0)
tk.Button(f1, text='修改订单', command=self.forget_pwd).grid(row=9,column=3)
except:
tk.Label(f1, text='暂时没有订单信息', fg='blue').grid(row=6, column=0)
tk.Button(f1, text='退出', command=self.leave).grid(row=9, column=0)
tk.Button(f1, text='修改订单', command=self.forget_pwd).grid(row=9, column=3)
f0.pack()
f1.pack()
top_order.mainloop()
## 用户选择退出程序,关闭数据库连接,关闭界面
def leave(self):
print '正在关闭数据库连接'
self.cursor.close()
self.conn.close()
print '数据库连接已经关闭'
print '正在关闭窗口'
self.root.withdraw()
self.root.destroy()
print '窗口关闭完成'
## 注册界面
def _register(self):
self.root.withdraw()
self.top_register = OtherFrame('你好')
self.top_register.title('账号注册')
top_pic = tk.Frame(self.top_register)
top = tk.Frame(self.top_register)
tk.Label(top_pic,image=img,bd=80,height=10,width=140).pack()
tk.Label(top, text='用户名').grid(row=1)
tk.Label(top, text='密码').grid(row=3)
tk.Label(top, text='确认密码').grid(row=5)
tk.Label(top, text='身份证号').grid(row=7)
tk.Label(top, text='电话').grid(row=9)
self.v1 = tk.StringVar()
self.v2 = tk.StringVar()
self.v3 = tk.StringVar()
self.v4 = tk.StringVar()
self.v5 = tk.StringVar()
e1 = tk.Entry(top, width=20,textvariable=self.v1) # 设置你的用户名
e2 = tk.Entry(top, width=20,show='*',textvariable=self.v2) # 设置你的密码
e3 = tk.Entry(top, width=20, show='*',textvariable=self.v3) # 确认你的密码
e4 = tk.Entry(top, width=20,textvariable=self.v4) # 设置你的身份号
e5 = tk.Entry(top, width=20,textvariable=self.v5) # 设置你的电话
e1.grid(row=1, column=1, padx=1, pady=1)
e2.grid(row=3, column=1, padx=1, pady=1)
e3.grid(row=5, column=1, padx=1, pady=1)
e4.grid(row=7, column=1, padx=1, pady=1)
e5.grid(row=9, column=1, padx=1, pady=1)
handle = lambda: self.close_open(self.top_register,self.root)
tk.Button(top, text='<<返回登陆界面',fg='white',bg='blue',
command=handle).grid(row=11, column=0, padx=10, pady=1)
tk.Button(top, text='>>注册你的账号',bg='blue',fg='white',
command=self.save_inf).grid(row=11, column=1, padx=10, pady=1)
self.register_var = tk.StringVar()
self.register_var.set('')
tk.Label(top,textvariable=self.register_var,fg='red').grid(row=13,column=1)
top_pic.pack()
top.pack()
self.top_register.mainloop()
## 存储用户的注册信息
def save_inf(self):
if self.v2.get() != self.v3.get():
self.register_var.set('两次密码输入不一致')
elif self.v1.get() in self.dict_inf.keys():
self.register_var.set('用户名已经存在')
elif self.v1.get()=='' or self.v2.get()=='' or self.v3.get()=='' or self.v4.get()==''or self.v5.get()=='':
self.register_var.set('信息输入不完整')
else:
try:
sql_insert = "insert into user_inf values('%s','%s','%s','%s')"%(self.v1.get(),self.v2.get(),self.v4.get(),self.v5.get())
self.cursor.execute(sql_insert)
self.conn.commit()
self.register_var.set('注册成功,点击跳转')
time.sleep(1)
register_to_login = lambda: self.close_open(self.top_register, top_login)
tk.Button(self.top_register,
text='注册成功,点击跳转',
command=register_to_login).grid(row=16)
except MySQLdb.Error as e:
self.conn.rollback()
print '写入错误'+str(e)
## 用户选忘记密码的响应,这里为了简便不提供支持,其实很简单
def forget_pwd(self):
print '这只是个按钮,暂不提供支持'
self.var1.set('~忘了吧,不提供支持了~')
if __name__ == "__main__":
root0 = MainFrame('酒店预定系统')
user_login(root0)
root0.mainloop()