BACKEND TODO:
- 数据表设计及初始化
- 数据库操作轮子重构
我们根据实际需求设计了数据表及字段,并规范了表之间的关系,编写了数据库初始化文件db_init.sql
;数据库操作泽同学手中有自己写的轮子,但由于基于python2.7因此要对其先进行语法重构。
阶段成果记录:
1. 数据表设计及初始化
Users记录用户信息,Problems表记录题目信息,WriteUp表记录题解信息,Record表记录提交记录,其中Users、Problems表与WriteUp、Record表是一对多(ER图略),其余表相互独立。所有表id字段主键自增,create_time及update_time采用datetime数据类型。
关于提交结果判断还有培欣的bitmap神奇操作,但考虑到逻辑上的清晰故仍使用Record表。
Users:
id | username | password | points | gender | create_time | update_time | |
---|---|---|---|---|---|---|---|
0 | dubhe | 85b2f42582a1606d79a8741d3f26e595 | [email protected] | 0 | M | 2018-10-25-8:53:10 | 2018-10-26-8:53:10 |
Problems:
id | name | tag | flag | content | points | create-time | update-time |
---|---|---|---|---|---|---|---|
0 | Web Puzzle 01 | web | flag{dubhe_best} | .... | 10 | 2018-10-25-8:53:10 | 2018-10-26-8:53:10 |
WriteUp:
id | uid | pid | content | create-time | update-time |
---|---|---|---|---|---|
0 | 0 | 0 | ... | 2018-10-25-8:53:10 | 2018-10-26-8:53:10 |
Record:
id | uid | pid | state | create_time | update_time |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 2018-10-25-8:53:10 | 2018-10-25-8:53:10 |
db_init.sql代码:
数据库初始化文件,Luty先写了基本的创表和初始数据插入,泽龙用phpadmin重构了一下,规范了格式。
-- phpMyAdmin SQL Dump
-- version 4.8.2
-- https://www.phpmyadmin.net/
--
-- Host: localhost:3306
-- Generation Time: Oct 28, 2018 at 07:19 PM
-- Server version: 5.7.21
-- PHP Version: 7.2.7
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
CREATE DATABASE IF NOT EXISTS CTF;
USE CTF;
--
-- Database: `CTF`
--
-- --------------------------------------------------------
--
-- Table structure for table `Problems`
--
CREATE TABLE `Problems` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL COMMENT '题目名称',
`tag` varchar(255) NOT NULL COMMENT '题目分类',
`flag` varchar(255) NOT NULL,
`content` text NOT NULL COMMENT '题目描述',
`points` float(11,2) NOT NULL COMMENT '题目分数(两位小数)',
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `Problems`
--
INSERT INTO `Problems` (`id`, `name`, `tag`, `flag`, `content`, `points`, `create_time`, `update_time`) VALUES
(1, 'Web Puzzle 01', 'web', 'flag{dubhe_best}', '[email protected]', 10.00, '2018-10-26 21:58:38', '2018-10-26 21:58:38');
-- --------------------------------------------------------
--
-- Table structure for table `Record`
--
CREATE TABLE `Record` (
`id` int(11) NOT NULL,
`uid` int(11) NOT NULL COMMENT '提交用户',
`pid` int(11) NOT NULL COMMENT '提交问题',
`state` int(11) NOT NULL COMMENT '提交结果',
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `Record`
--
INSERT INTO `Record` (`id`, `uid`, `pid`, `state`, `create_time`, `update_time`) VALUES
(1, 0, 0, 0, '2018-10-26 21:58:38', '2018-10-26 21:58:38');
-- --------------------------------------------------------
--
-- Table structure for table `Users`
--
CREATE TABLE `Users` (
`id` int(11) NOT NULL,
`username` varchar(255) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '密码',
`email` varchar(255) NOT NULL COMMENT '电子邮箱',
`points` float(11,2) NOT NULL COMMENT '获得分数(两位小数)',
`gender` varchar(255) NOT NULL COMMENT '性别',
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `Users`
--
INSERT INTO `Users` (`id`, `username`, `password`, `email`, `points`, `gender`, `create_time`, `update_time`) VALUES
(1, 'duhbe', '85b2f42582a1606d79a8741d3f26e595', '[email protected]', 10.00, 'M', '2018-10-26 21:58:38', '2018-10-26 21:58:38'),
(2, 'a', 'a', 'a', 123.00, 'a', '2018-10-26 00:00:00', '2018-10-26 00:00:00');
-- --------------------------------------------------------
--
-- Table structure for table `WriteUp`
--
CREATE TABLE `WriteUp` (
`id` int(11) NOT NULL,
`uid` int(11) NOT NULL COMMENT '所属用户',
`pid` int(11) NOT NULL COMMENT '所属题目',
`content` text NOT NULL,
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `WriteUp`
--
INSERT INTO `WriteUp` (`id`, `uid`, `pid`, `content`, `create_time`, `update_time`) VALUES
(1, 0, 0, 'this is a WriteUp', '2018-10-26 21:58:38', '2018-10-26 21:58:38');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `Problems`
--
ALTER TABLE `Problems`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `Record`
--
ALTER TABLE `Record`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `Users`
--
ALTER TABLE `Users`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `username` (`username`),
ADD UNIQUE KEY `email` (`email`);
--
-- Indexes for table `WriteUp`
--
ALTER TABLE `WriteUp`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `Problems`
--
ALTER TABLE `Problems`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT for table `Record`
--
ALTER TABLE `Record`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT for table `Users`
--
ALTER TABLE `Users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT for table `WriteUp`
--
ALTER TABLE `WriteUp`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
2. 后端轮子重构
上述是Luty写的,写的很有水平,我现在有些害怕。
原来的轮子是用Python2.7编写的,所以需要重构
数据库模块重构
原来使用的是MySQLdb
但这个令人头疼的包,他居然不与时俱进!!(不与时俱进就要被淘汰啊)。所以他就被抛弃了。(可怜)
MySQLdb 语法解释
原来的MySQLdb是相当的麻烦,你们可以从MySQLdb这里可以看出来。
pymysql 解释
既然MySQLdb是如此的麻烦,那么pymysql是不是简单些呢? 巧了 ,pymysql甚至更加的麻烦pymysql,从这里看的出来真不巧啊。所以我们需要再次封装
那他有什么与MySQLdb有什么不一样呢?
据我所知,一个是提交代码需要用commit()
,如果执行错误还要rollback()
,这可是前任不需要的啊。真矫情!
其他重构细节
1.原来我所使用的输入输出库是第三方库,被改良过的,可以输出各种颜色(真强),现在使用服务器上,这东西怕是用不了了。就改成了print()
了。
2.原来我的轮子使用的比较繁琐,需要先start(),在执行,在stop()
,在原本的情况下,Luty可能会嫌弃我的轮子,所以我改良了一下,就不用start()
stop()
了。
这里贴出源码
import pymysql
class Mysql:
"""
Mysql库用法x
1.初始化数据库类
2.执行操作
"""
def __init__(self, user, password, host, port, db):
self.__user = user
self.__password = password
self.__host = host
self.__port = port
self.__db = db
# 初始化各种变量
def start(self):
try:
self.__conn = pymysql.connect(
host=self.__host,
user=self.__user,
passwd=self.__password,
port=self.__port,
db=self.__db,
charset='utf8mb4', # 数据库编码类型
)
self.__cursor = self.__conn.cursor()
return True # 调用时判断是否执行成功
except Exception as e:
print(e)
return False
def stop(self):
self.__cursor.close()
self.__conn.close()
def query(self, query): # 执行query语句,返回所有结果
try:
self.start()
self.__cursor.execute(query)
self.__conn.commit()
self.stop()
return self.__cursor.fetchall()
except Exception as e:
self.__conn.rollback()
print(e)
return False
finally:
pass
def execute(self, query): # 用于执行不需要返回值的语句,返回True 或 False
_bool = True # 用于记录语句是否执行成功
try:
self.start()
self.__cursor.execute(query)
self.__conn.commit()
self.stop()
except Exception as e:
print(e)
self.__conn.rollback()
return False
finally:
return _bool
def insert(self, table, data):
# 数据库插入操作 这里如果有引号请自己在data中转义 无法自动判断
name = []
value = []
for key in data:
name.append('`' + str(key) + '`') # 这里的str是防止输入的是数字
value.append(str(data[key]))
query = 'insert into `' + table + \
'` (' + ','.join(name) + ') values (' + ','.join(value) + ')'
return self.execute(query)
def delete(self, table, where='1=2'):
# 删除行 一定不要把where写成永远为真的值
query = 'delete from `' + table + '` where ' + where
return self.execute(query)
def update(self, table, data, where='1=2'):
# 更新行 记得如果是字符串单引号转义
sets = []
for key in data:
sets.append('`' + str(key) + '`=' + str(data[key]))
query = 'update `' + table + '` set ' + ','.join(sets) + ' where ' + where
return self.execute(query)
def select(self, table, key, where, suffix=''):
# select行 suffix是指如果要查询order by ,union之类的东西写的
if len(key) == 0:
key = ['*']
value = ','.join(key)
query = 'select ' + value + ' from `' + table + '` where ' + where + ' ' + suffix
return self.query(query)
请忍受我的代码,别开枪打死我。