本文介绍如何在云服务器(CentOS)上安装MySQL数据库(其实是MariaDB数据库,但是当成MySQL用也没什么问题),并用pymysql或peewee与原生Python代码进行互动,或用Flask-SQLAlchemy与Flask进行互动。
之所以不直接租个数据库是因为暂时来说服务器的储存空间还够用。
关于pymysql和Flask-SQLAlchemy的选择,可以参考ChatGPT-4的回答:
如果你正在使用Flask来开发一个Web应用,Flask-SQLAlchemy是一个很好的选择,它提供了更高级的数据库抽象,支持更复杂的ORM模式,并且与Flask紧密集成。但是如果你的需求比较简单,或者你更喜欢直接使用SQL语句,那么pymysql就足够好了。
文章目录
1. CentOS云服务器安装MySQL数据库
我记得有的镜像好像是默认安装MySQL的,但反正我没有。
可以用这个命令查证一下:mysql --version
没安装的话就会返回这个信息:bash: mysql: command not found
安装后就会返回类似的信息:mysql Ver 8.0.26 for Linux on x86_64 (Source distribution)
root用户运行:yum install mysql
(如果用普通用户运行,就会报这个信息:Error: This command has to be run with superuser privileges (under the root user on most systems).
)
以下流程也都用root用户运行:
yum install mysql-server
systemctl start mysqld
systemctl enable mysqld
安装服务器→启动→设置开启自启动(不过看介绍说好像这一条不太需要,因为MySQL默认开启)
查看MySQL的运行状态:systemctl status mysqld
注意接下来的步骤比较微妙:我的情况是mysqld的位置在/var/log/mysql/mysqld.log
,这个文件的内容是:
这玩意居然是空密码开启的……别的教程里面都可以用sudo grep 'temporary password' /var/log/mysqld.log
这个命令获取临时密码的。
据说这是因为服务器版本的问题。
总之我是空密码登录:mysql -u root -p
进入MySQL环境中就可以使用SQL语言来进行工作了(具体命令可以查看我之前写的博文:MySQL命令行速查手册(持续更新ing…) )
exit
或者quit
退出MySQL环境。
2. PyMySQL包
PyMySQL包差不多就是直接用Python写SQL语言了。
官方GitHub项目:PyMySQL/PyMySQL: MySQL client library for Python
官方文档:Welcome to PyMySQL’s documentation! — PyMySQL 0.7.2 documentation
安装方式:pip install PyMySQL
用with
上下文管理器的示例代码(往表格中插入一条信息,查询这条信息):
import pymysql.cursors
# Connect to the database
connection = pymysql.connect(host='localhost',
user='New-Username',
password='New-Password',
db='New-DatabaseName',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
with connection:
with connection.cursor() as cursor:
# Create a new record
sql = "INSERT INTO `users` (`phone_number`, `password`) VALUES (%s, %s)"
cursor.execute(sql, (phone_number,password))
# connection is not autocommit by default. So you must commit to save
# your changes.
connection.commit()
with connection.cursor() as cursor:
# Read a single record
sql = "SELECT `id`, `password` FROM `users` WHERE `phone_number`=%s"
cursor.execute(sql, (phone_number,))
result = cursor.fetchone()
print(result)
手动设置开关文件流的示例代码(往表格中插入一条信息):
import openpyxl
import pymysql.cursors
# Connect to the database
connection = pymysql.connect(host='localhost',
user='New-Username',
password='New-Password',
db='New-DatabaseName',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
cursor = connection.cursor()
cursor.execute("""
INSERT INTO Papers (
title, authors, summary, paper_url, publication_date, updated_date, is_legalAI
) VALUES (%s, %s, %s, %s, %s, %s, %s)
""", (title, authors, summary, paper_url, publication_date_str, updated_date_str, is_legalAI))
# 提交事务,保存到数据库
connection.commit()
# 关闭数据库连接
cursor.close()
connection.close()
执行查询命令:
cursor.execute("SELECT * FROM Papers WHERE LOWER(title) = LOWER(%s)", (title,))
result = cursor.fetchone()
result返回的是一个样本,是元组或是字典(设置cursorclass=pymysql.cursors.DictCursor
时。用列名提取属性值)
其他注意事项:
- 对于MySQL中DATE属性的列,从Python传入的字符串,如原始
2001-06-07T14:40:04Z
,可以通过这样的步骤进行转换:
↑然后传入mysql_date这个对象就可以from datetime import datetime # 原始字符串 date_string = "2001-06-07T14:40:04Z" # 将字符串转换为datetime对象 dt = datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%SZ") # 将datetime对象格式化为MySQL可以接受的日期格式 mysql_date = dt.strftime("%Y-%m-%d")
- ↑这个代码只提取了日期部分,没有时间部分,因为数据库列是DATE类型,只能存储日期,不能存储时间。如果数据库列是DATETIME类型,可以存储日期和时间,那么可以使用
strftime("%Y-%m-%d %H:%M:%S")
来格式化datetime对象。 - 特殊功能实现
- 将字典插入数据库:
import pymysql # 创建连接 conn = pymysql.connect(host='your_host', user='your_username', password='your_password', db='your_db', charset='utf8') # 创建游标 cursor = conn.cursor() data_dict = {"column1": "value1", "column2": "value2", "column3": "value3"} # 你的字典数据 table_name = "your_table" # 你的表名 keys = ', '.join(data_dict.keys()) values = ', '.join(['%s'] * len(data_dict)) sql = 'INSERT INTO {table} ({keys}) VALUES ({values})'.format(table=table_name, keys=keys, values=values) try: if cursor.execute(sql, tuple(data_dict.values())): print('Successful') conn.commit() except: print('Failed') conn.rollback() # 关闭游标和连接 cursor.close() conn.close()
- 按照字典更新数据库:
import pymysql # 创建连接 conn = pymysql.connect(host='your_host', user='your_username', password='your_password', db='your_db', charset='utf8') # 创建游标 cursor = conn.cursor() data_dict = {"column1": "new_value1", "column2": "new_value2"} # 你的字典数据 table_name = "your_table" # 你的表名 condition = "column3 = 'value3'" # 更新的条件 data = ', '.join([f"{k}=%s" for k in data_dict.keys()]) sql = f'UPDATE {table_name} SET {data} WHERE {condition}' try: if cursor.execute(sql, tuple(data_dict.values())): print('Successful') conn.commit() except: print('Failed') conn.rollback() # 关闭游标和连接 cursor.close() conn.close()
- 按照字典更新数据库,这个是where语句也是字符串格式,需要判断的条件。然后别的部分不用重复写:
data = ', '.join([f"{k}=%s" for k in paper.keys()]) values = tuple(paper.values()) + (paper["title"],) cursor.execute(f""" UPDATE Papers SET {data} WHERE LOWER(title) = LOWER(%s) """, values)
3. Flask-SQLAlchemy包
官方GitHub项目:pallets-eco/flask-sqlalchemy: Adds SQLAlchemy support to Flask
官方速成教程:Quick Start — Flask-SQLAlchemy Documentation (3.0.x)
安装方式:pip install -U Flask-SQLAlchemy
注意Python 3+必须要安装pymysql,才能正常用Flask-SQLAlchemy,因为如果不用pymysql引擎,就会需要用MySQLdb这个包,但是这个包只支持Python 2。
在flask应用中导入:
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy.orm import sessionmaker
db=SQLAlchemy()
app.config["SQLALCHEMY_DATABASE_URI"]="mysql+pymysql://MySQL用户名:MySQL用户密码@localhost/database名"
#localhost是数据库的IP地址
db.init_app(app)
with app.app_context():
db.create_all() #也可以不用这句话,直接在该上下文中运行Flask-SQLAlchemy命令
写db.Model
类:每个db.Model
就相当于一个table,会自动与数据库中实际存在的表相连,如果数据库中不存在会创建。关联方式是要么用__tablename__
指定,要么根据db.Model
类名来指定(如类名为User
,默认表名就是user
;类名为UserUsage
,默认表名就是user_usage
):
(这里多用了一个包:Werkzeug
官方文档:Werkzeug — Werkzeug Documentation (2.3.x)
安装方式:pip install Werkzeug
这个包我以后可能会专门写个介绍博文,现在就直接用就行)
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
import datetime
class User(UserMixin,db.Model):
__tablename__='users'
id=db.Column(db.Integer,primary_key=True)
phone_number=db.Column(db.String,unique=True,nullable=False)
nickname=db.Column(db.String)
password=db.Column(db.String)
email=db.Column(db.String)
memo=db.Column(db.String)
def set_password(self,password):
"""将password加密"""
self.password=generate_password_hash(password)
def check_password(self,password):
"""检查用户输入的密码加密后,是否与储存的密码相同"""
return check_password_hash(self.password,password)
class ChatBotIO(db.Model):
__tablename__='chatbot_io'
id=db.Column(db.Integer,primary_key=True)
user_id=db.Column(db.Integer,nullable=False)
phone_number=db.Column(db.String,unique=True,nullable=False)
service_name=db.Column(db.String,nullable=False)
user_input=db.Column(db.String)
system_output=db.Column(db.String)
now_time=db.Column(db.DateTime,default=datetime.datetime.now)
class UserUsage(db.Model): #用户的每日使用数量
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
date = db.Column(db.Date, default=datetime.datetime.now)
dialogues = db.Column(db.Integer, default=0)
tokens = db.Column(db.Integer, default=0)
- 创建一个样本对象:
- 常规写法(一次性初始化所有属性):
today = datetime.datetime.now().date() usage = UserUsage(user_id=current_user.id, date=today)
- 特殊写法
user=User(phone_number=phone_number) user.set_password(password)
- 将样本增加到数据库中:
db.session.add(user)
db.session.commit()
- 将样本从数据库中删除:
user = User.query.filter_by(phone_number='13451245454').first()
if user:
# 删除用户
db.session.delete(user)
db.session.commit()
- 查询样本:
user=User.query.filter_by(phone_number=form.phone.data).first()
(如果不存在,将返回None
)
4. 其他Python包
1 peewee包
peewee包官方文档:peewee — peewee 3.16.2 documentation
2 SQLAlchemy包
SQLAlchemy包官方文档:SQLAlchemy - The Database Toolkit for Python
3 MySQL Connector/Python包
这是MySQL官方提供的。
pypi主页:https://pypi.org/project/mysql-connector-python/
4 SQLObject包
SQLObject包官方文档:SQLObject — SQLObject 3.10.1 documentation
5. 本文撰写过程中参考的网络资料
- How To Install MySQL on CentOS 7 | DigitalOcean
- How to Start, Stop, and Restart MySQL Server - Hivelocity Hosting
- CentOS MySQL安装及问题解决_grep: /var/log/mysqld.log: no such file or directo_Charlie。的博客-CSDN博客
- 【MySQL入门】(五)Flask使用MySQL存储数据_flask mysql_DooDoo~的博客-CSDN博客
- python - ImportError: No module named MySQLdb - Stack Overflow
- Python 3 ImportError: No module named ‘ConfigParser’ - Stack Overflow
- flask博客项目阿里云ECS部署
- html - How to prevent the browser from asking for the favicon? - Stack Overflow:答案是没啥影响,不嫌弃就不去掉也行
- How To Redirect To Url In Python Flask – vegibit