电影订票系统后台开发(2)数据模型

电影订票系统后台开发(2)数据模型
完整项目请戳 猿眼电影订票系统

Let’s go

项目开发环境

  • Deepin-Linux 15.4
  • Python 2.7.12
  • PyCharm
  • Flask
  • MySQL 5.6
  • Navicat Premium

软件安装

  • Navicat Premium

Navicat Premium 是一款数据库管理工具,可连接到 MySQL、PostgreSQL、SQLite、Oracle 及 MariaDB 等数据库,让管理不同类型的数据库更加方便。前往 Navicat Premium 官网 下载并安装即可,破解方法自行百度。

  • PowerDesigner

PowerDesigner 可以方便地对管理信息系统进行分析设计,它几乎包括了数据库模型设计的全过程,可以制作数据流程图、概念数据模型、物理数据模型,还可以为数据仓库制作结构模型,也能对团队设计模型进行控制。PowerDesigner 是能进行数据库设计的强大的软件,是一款开发人员常用的数据库建模工具。不过如果只是简单的进行数据库建模,也可直接使用 Navicat Premium 的模型功能。

  • MySQL

本项目使用 MySQL 数据库,前往 MySQL 官网 下载对应系统的安装包安装即可。

数据库建模

猿眼电影订票系统的主要功能是用户可以浏览电影信息并选择场次和座位进行下单购票,完成支付后会随机赠送优惠券,可在下次购票时使用。观看完电影之后可进行电影评论,用户也可以收藏电影,首页会定期推荐新上映的热门电影,因此该项目至少涉及以下几张数据表:用户表,电影表,场次表,订单表,评论表,优惠券表,推荐表,收藏表。
完整的数据库模型如下图:
数据库模型
对应的sql语句如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
-- ----------------------------
-- Table structure for users 用户表
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` varchar(11) NOT NULL COMMENT '用户id(手机号码)',
`password` varchar(32) NOT NULL COMMENT '登录密码',
`payPassword` varchar(32) NOT NULL COMMENT '支付密码',
`nickname` varchar(20) NOT NULL DEFAULT '' COMMENT '昵称',
`money` float NOT NULL COMMENT '余额',
`description` varchar(50) NOT NULL DEFAULT '' COMMENT '个性签名',
`avatar` varchar(32) NOT NULL DEFAULT '' COMMENT '头像路径',
`isAdmin` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for movies 电影表
-- ----------------------------
DROP TABLE IF EXISTS `movies`;
CREATE TABLE `movies` (
`id` varchar(32) NOT NULL,
`name` varchar(25) NOT NULL COMMENT '电影名称',
`description` text NOT NULL COMMENT '电影描述',
`playingTime` date NOT NULL COMMENT '上映时间',
`duration` smallint(6) NOT NULL COMMENT '时长',
`movieType` varchar(20) NOT NULL COMMENT '电影类型',
`playingType` varchar(15) NOT NULL COMMENT '放映类型',
`expired` tinyint(1) DEFAULT '0' COMMENT '是否下架',
`rating` float DEFAULT NULL COMMENT '评分',
`ratingNum` smallint(6) DEFAULT NULL COMMENT '评分人数',
`poster` varchar(40) DEFAULT NULL COMMENT '海报路径',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for screens 场次表
-- ----------------------------
DROP TABLE IF EXISTS `screens`;
CREATE TABLE `screens` (
`id` varchar(32) NOT NULL,
`movieId` varchar(32) NOT NULL,
`time` datetime NOT NULL COMMENT '场次时间',
`price` float NOT NULL COMMENT '票价',
`ticketNum` smallint(6) NOT NULL DEFAULT '120' COMMENT '总票数',
`hallNum` varchar(1) NOT NULL COMMENT '放映厅',
`playingType` varchar(10) NOT NULL COMMENT '放映类型',
PRIMARY KEY (`id`),
KEY `movieId` (`movieId`),
CONSTRAINT `screens_ibfk_1` FOREIGN KEY (`movieId`) REFERENCES `movies` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for comments 评论表
-- ----------------------------
DROP TABLE IF EXISTS `comments`;
CREATE TABLE `comments` (
`id` varchar(32) NOT NULL,
`username` varchar(11) NOT NULL COMMENT '手机号码',
`movieId` varchar(32) NOT NULL COMMENT '电影id',
`content` text NOT NULL COMMENT '评论内容',
`rating` smallint(6) NOT NULL COMMENT '评分',
PRIMARY KEY (`id`),
KEY `username` (`username`),
KEY `movieId` (`movieId`),
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`username`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `comments_ibfk_2` FOREIGN KEY (`movieId`) REFERENCES `movies` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for coupons 优惠券表
-- ----------------------------
DROP TABLE IF EXISTS `coupons`;
CREATE TABLE `coupons` (
`id` varchar(32) NOT NULL,
`discount` smallint(2) NOT NULL COMMENT '折扣',
`condition` smallint(3) NOT NULL COMMENT '满多少可用',
`username` varchar(11) NOT NULL COMMENT '手机号码',
`expiredTime` date NOT NULL COMMENT '过期日期',
`status` tinyint(1) NOT NULL COMMENT '优惠券状态(0:未用 1:已用)',
PRIMARY KEY (`id`),
KEY `username` (`username`),
CONSTRAINT `coupons_ibfk_1` FOREIGN KEY (`username`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for favorites 收藏表
-- ----------------------------
DROP TABLE IF EXISTS `favorites`;
CREATE TABLE `favorites` (
`id` varchar(32) NOT NULL,
`username` varchar(11) NOT NULL,
`movieId` varchar(32) NOT NULL,
PRIMARY KEY (`id`),
KEY `username` (`username`),
KEY `movieId` (`movieId`),
CONSTRAINT `favorites_ibfk_1` FOREIGN KEY (`username`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `favorites_ibfk_2` FOREIGN KEY (`movieId`) REFERENCES `movies` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for orders 订单表
-- ----------------------------
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
`id` varchar(32) NOT NULL,
`screenId` varchar(32) NOT NULL COMMENT '场次id',
`seat` blob NOT NULL COMMENT '座位号',
`username` varchar(11) NOT NULL COMMENT '手机号码',
`createTime` datetime NOT NULL COMMENT '创建时间',
`status` tinyint(1) NOT NULL COMMENT '订单状态(0: 未支付 1: 已支付)',
`couponId` varchar(32) DEFAULT NULL COMMENT '优惠券id',
`totalPrice` float DEFAULT NULL COMMENT '总价',
`payPrice` float DEFAULT NULL COMMENT '实际支付',
PRIMARY KEY (`id`),
KEY `screenId` (`screenId`),
KEY `username` (`username`),
KEY `couponId` (`couponId`) USING BTREE,
CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`screenId`) REFERENCES `screens` (`id`),
CONSTRAINT `orders_ibfk_2` FOREIGN KEY (`username`) REFERENCES `users` (`id`),
CONSTRAINT `orders_ibfk_3` FOREIGN KEY (`couponId`) REFERENCES `coupons` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for recommends 推荐表
-- ----------------------------
DROP TABLE IF EXISTS `recommends`;
CREATE TABLE `recommends` (
`movieId` varchar(32) NOT NULL,
PRIMARY KEY (`movieId`),
CONSTRAINT `recommends_ibfk_1` FOREIGN KEY (`movieId`) REFERENCES `movies` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

对象关系映射 ORM

对象关系映射(Object Relational Mapping,简称ORM),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。对象关系映射(Object-Relational Mapping)提供了概念性的、易于理解的模型化数据的方法。在大多数的 Web 应用中,都会将数据存储在 关系型数据库中,使用 ORM 技术可以在代码通过操作对象实现数据库操作,无需自己写sql语句,如前面一大段建表的语句,ORM模型的简单性简化了数据库查询过程。使用ORM查询工具,用户可以访问期望数据,而不必理解数据库的底层结构。在 Flask 中可使用Flask-SQLAlchemy来实现 ORM。

1
2
(venv) $ pip install Flask-SQLAlchemy   # 安装 Flask-SQLAlchemy
(venv) $ pip freeze > requiremens.txt # 更新需求文件

安装完后在项目文件夹下新建models.py文件,此时项目结构如下:

1
2
3
4
5
6
7
8
9
10
MonkeyEye/
├── app
│   ├── static/ # 静态资源文件夹
│   ├── templates/ 模板文件夹
│   ├── __init__.py
│   ├── server.py # 主程序文件
│   └── models.py # 数据模型
├── requirements # 需求文件
├── venv/ # 虚拟环境
└── README.md

models.py 内容如下,relationship 用于定义外键,SQLAlchemy 快速入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# -*- coding: utf-8 -*-
from datetime import datetime, date
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


class User(db.Model):
"""用户"""
__tablename__ = 'users'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键

id = db.Column(db.String(11), doc='手机号码', primary_key=True)
password = db.Column(db.String(32), doc='密码', nullable=False)
payPassword = db.Column(db.String(32), doc='支付密码', nullable=False)
nickname = db.Column(db.String(20), doc='昵称', default='猿眼用户', nullable=False)
money = db.Column(db.Float, doc='账户余额', default=50, nullable=False)
description = db.Column(db.String(50), doc='个性签名', default='这个人很懒,什么也没留下', nullable=False)
avatar = db.Column(db.String(32), doc='头像路径', default='MonkeyEye.webp')
isAdmin = db.Column(db.Boolean, doc='是否管理员', default=False)

orders = db.relationship('Order', backref='users', cascade='all', lazy='dynamic')
coupons = db.relationship('Coupon', backref='users', cascade='all', lazy='dynamic')
favorites = db.relationship('Favorite', backref='users', cascade='all', lazy='dynamic')
comments = db.relationship('Comment', backref='users', cascade='all', lazy='dynamic')


class Movie(db.Model):
"""电影"""
__tablename__ = 'movies'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键

id = db.Column(db.String(32), primary_key=True)
expired = db.Column(db.Boolean, doc='是否下架', default=False, nullable=False)
name = db.Column(db.String(25), doc='电影名称', nullable=False)
description = db.Column(db.Text, doc='电影介绍', default='暂无介绍', nullable=False)
playingTime = db.Column(db.Date, doc='上映时间', default=date.today(), nullable=False)
duration = db.Column(db.SmallInteger, doc='电影时长(分钟)', nullable=False)
movieType = db.Column(db.String(20), doc='电影类型', nullable=False)
playingType = db.Column(db.String(15), doc='放映类型', nullable=False)
rating = db.Column(db.Float, doc='电影评分', default=0)
ratingNum = db.Column(db.SmallInteger, doc='评分人数', default=0)
poster = db.Column(db.String(40), doc='海报路径')

screens = db.relationship('Screen', backref='movies', cascade='all', lazy='dynamic')
recommends = db.relationship('Recommend', backref='movies', cascade='all', lazy='dynamic')
comments = db.relationship('Comment', backref='movies', cascade='all', lazy='dynamic')
favorites = db.relationship('Favorite', backref='movies', cascade='all', lazy='dynamic')


class Screen(db.Model):
"""场次"""
__tablename__ = 'screens'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键

id = db.Column(db.String(32), primary_key=True)
movieId = db.Column(db.String(32), db.ForeignKey('movies.id'), nullable=False)
time = db.Column(db.DateTime, doc='场次时间', default=datetime.now(), nullable=False)
hallNum = db.Column(db.String(1), doc='放映厅(1-5)', nullable=False)
price = db.Column(db.Float, doc='票价', default=30, nullable=False)
ticketNum = db.Column(db.SmallInteger, doc='电影总票数', default=120, nullable=False)

orders = db.relationship('Order', backref='screens', cascade='all', lazy='dynamic')


class Recommend(db.Model):
"""推荐"""
__tablename__ = 'recommends'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键

movieId = db.Column(db.String(32), db.ForeignKey('movies.id'), primary_key=True, nullable=False)


class Order(db.Model):
"""订单"""
__tablename__ = 'orders'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键

id = db.Column(db.String(32), primary_key=True)
screenId = db.Column(db.String(32), db.ForeignKey('screens.id'), nullable=False)
seat = db.Column(db.PickleType, doc='座位号(逗号分隔)', nullable=False)
username = db.Column(db.String(32), db.ForeignKey('users.id'), nullable=False)
createTime = db.Column(db.DateTime, doc='创建时间', nullable=False)
status = db.Column(db.Boolean, doc='订单状态(0:未支付,1:已支付)', default=0, nullable=False)
couponId = db.Column(db.String(32), db.ForeignKey('coupons.id'))
payPrice = db.Column(db.Float, doc='实际支付', nullable=False)
totalPrice = db.Column(db.Float, doc='原价', nullable=False)


class Coupon(db.Model):
"""优惠券"""
__tablename__ = 'coupons'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键

id = db.Column(db.String(32), primary_key=True)
discount = db.Column(db.SmallInteger, doc='折扣', nullable=False, default=5)
condition = db.Column(db.SmallInteger, doc='满多少元可用', default=30, nullable=False)
username = db.Column(db.String(32), db.ForeignKey('users.id'), nullable=False, doc='手机号码')
expiredTime = db.Column(db.Date, doc='过期时间', nullable=False)
status = db.Column(db.Boolean, doc='状态(0:未使用,1:已使用)', default=0, nullable=False)


class Favorite(db.Model):
"""收藏"""
__tablename__ = 'favorites'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键

id = db.Column(db.String(32), primary_key=True)
username = db.Column(db.String(32), db.ForeignKey('users.id'), nullable=False, doc='手机号码')
movieId = db.Column(db.String(32), db.ForeignKey('movies.id'), nullable=False)


class Comment(db.Model):
"""评论"""
__tablename__ = 'comments'
__table_args__ = {'mysql_engine': 'InnoDB'} # 支持事务操作和外键

id = db.Column(db.String(32), primary_key=True)
username = db.Column(db.String(32), db.ForeignKey('users.id'), nullable=False, doc='手机号码')
movieId = db.Column(db.String(32), db.ForeignKey('movies.id'), nullable=False)
content = db.Column(db.Text, nullable=False, doc='评论内容')
rating = db.Column(db.SmallInteger, nullable=False, doc='电影评分')

然后在server.py中把 Flask 应用传递给 db 作为初始化参数即可,需要配置数据库的ip和端口,以及连接数据库所需的账号密码。

1
2
3
4
5
6
7
8
9
10
11
12
# *-* coding: utf-8 *-*
from models import db
from flask import Flask

app = Flask(__name__)

if __name__ == '__main__':
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://user:password@host:port/database'
db.app = app
db.init_app(app)
db.create_all() # 建表
app.run()

成功运行后使用 Navicat Premium 连接上数据库可以看到已经成功新建了8个数据库表
数据库表

文章目录
  1. Let’s go
    1. 项目开发环境
    2. 软件安装
    3. 数据库建模
    4. 对象关系映射 ORM
|
-->