1、子域名
子域名在许多网站中都用到了,比如一个网站叫做xxx.com,那么我们可以定义一个子域名cms.xxx.com来作为cms管理系统的网址,子域名的实现一般也是通过蓝图来实现,我们创建蓝图的时候添加了一个url_prefix=/user作为url前缀,那样我们就可以通过/user/来访问user下的url。但使用子域名则不需要。另外,还需要配置SERVER_NAME。
比如app.config[SERVER_NAME]=‘example.com:9000’。并且在注册蓝图的时候,还需要添加一个subdomain的参数,这个参数就是子域名的名称。
子域名cms.py实现
from flask import Blueprint
# subdomain="cms"是子域名名称
cms_bp = Blueprint("cms", __name__, subdomain="cms")
@cms_bp.route("/")
def cms_fun():
return "子域名cms页面"
主app.py实现
from flask import Flask, url_for
from blueprints.cms import cms_bp # 导入cms.py文件中的cms_bp
app = Flask(__name__)
app.register_blueprint(cms_bp)
# https://cms.127.0.0.1:5000/ cms视图函数
# Mac系统 /etc/hosts
# Windows系统 C:\Windows\System32\drivers\etc\hosts文件 进行修改
# 127.0.0.1 -------> host.com
# 127.0.0.1 -------> cms.host.com
# flask中不支持 IP形式和localhost,例如:cms.127.0.0.1:5000 cms.localhost:5000
app.config['SERVER_NAME'] = 'host.com:8888' # 这个flask项目实现在host.com网页,端口为8888,设置这个'SERVER_NAME'之后之前的127.0.0.1本地网页就不能打开了
@app.route("/")
def index():
print(url_for("news.news")) # 反转url news.是根据Blueprint('news')中的第一个参数来确定的 后一个是写方法名
print(url_for("books.book_detail", bid=5)) # 反转url book_detail是方法名称 bid=5是book_detail方法中需要传的参数
return "首页"
if __name__ == '__main__':
app.run(debug=True)
子域名实现步骤如下:
-
Mac系统 中修改 /etc/hosts
Windows系统中修改C:\Windows\System32\drivers\etc\hosts文件 设置为:
127.0.0.1 host.com
127.0.0.1 cms.host.com
注意:上面的cms子域名是cms.py文件中的subdomain="cms"设置的;
而且:flask中不支持 IP形式和localhost,例如:cms.127.0.0.1:5000 cms.localhost:5000这样形式的url -
设置SERVER_NAME
app.config['SERVER_NAME'] = 'host.com:8888'
# 这个flask项目实现在host.com网页,端口为8888,设置这个'SERVER_NAME'之后之前的127.0.0.1本地网页就不能打开了
注意:flask项目实现在host.com网页,端口为8888,设置这个’SERVER_NAME’之后之前的127.0.0.1本地网页就不能打开了。
如果注销这句代码,网页url还会显示为:127.0.0.1:5000
最终的子域名实现效果如下:
2、数据库
• 持久化存储
• 读写速度极高
• 保证数据的有效性 (必须存入给定的数据类型和种类)
• 对程序支持性非常好,容易扩展
理解数据库
• 数据行(记录)
• 数据列(字段)
• 数据表(数据行的集合)
• 数据库(数据表的集合)
MySql这部分详情可以看我之前的博客:数据库的学习
里面有介绍配置环境变量和需要安装的软件:PhpStudy和SQLyog
3、SQLAlchemy介绍和基本使用
数据库是一个网站的基础。Flask可以使用很多种数据库。比如MySQL,MongoDB,SQLite,PostgreSQL等。这里我们以MySQL为例进行讲解。而在Flask中,如果想要操作数据库,我们可以使用ORM来操作数据库,使用ORM操作数据库将变得非常简单。
在讲解Flask中的数据库操作之前,先要安装这些模块
- mysql:如果是在windows上,到官网下载。如果是ubuntu,通过命令sudo apt-get install mysql-server libmysqlclient-dev -yq进行下载安装。
- pymysql:pymysql是用Python来操作mysql的包,因此通过pip来安装,命令如下:pip3 install pymysql
- SQLAlchemy:SQLAlchemy是一个数据库的ORM框架,我们在后面会用到。安装命令为:pip3 install SQLAlchemy。
安装项目需要的库:
C:\Users\Administrator
λ cd /d E:\ENV\flask项目
E:\ENV\flask项目
λ pipenv shell
Launching subshell in virtual environment…
E:\ENV\flask项目
(flask项目-cBMOsSmb) λ pip list
Package Version
------------ -------
click 7.1.1
Flask 1.1.2
itsdangerous 1.1.0
Jinja2 2.11.1
MarkupSafe 1.1.1
pip 20.0.2
setuptools 46.1.3
Werkzeug 1.0.1
wheel 0.34.2
E:\ENV\flask项目
(flask项目-cBMOsSmb) λ pip install pymysql
Collecting pymysql
Using cached PyMySQL-0.9.3-py2.py3-none-any.whl (47 kB)
Installing collected packages: pymysql
Successfully installed pymysql-0.9.3
E:\ENV\flask项目
(flask项目-cBMOsSmb) λ pip install SQLAlchemy -i https://pypi.mirrors.ustc.edu.cn/simple/
Looking in indexes: https://pypi.mirrors.ustc.edu.cn/simple/
Collecting SQLAlchemy
Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/aa/7b05b5aa7baef1d4f9b3e5ecacf495098c7a0ef6541e74db3c802eff7
2/SQLAlchemy-1.3.16-cp36-cp36m-win_amd64.whl (1.2 MB)
|████████████████████████████████| 1.2 MB 1.7 MB/s
Installing collected packages: SQLAlchemy
Successfully installed SQLAlchemy-1.3.16
E:\ENV\flask项目
(flask项目-cBMOsSmb) λ pip install mysql-connector -i https://pypi.mirrors.ustc.edu.cn/simple/
Looking in indexes: https://pypi.mirrors.ustc.edu.cn/simple/
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ReadTimeoutError
HTTPSConnectionPool(host='mirrors.ustc.edu.cn', port=443): Read timed out. (read timeout=15)",)': /pypi/web/simple/mysql-connector/
Collecting mysql-connector
Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/04/e40098f3730e75bbe36a338926f566ea803550a34fb50535499f4fc47
a/mysql-connector-2.2.9.tar.gz (11.9 MB)
|████████████████████████████████| 11.9 MB 172 kB/s
Building wheels for collected packages: mysql-connector
Building wheel for mysql-connector (setup.py) ... done
Created wheel for mysql-connector: filename=mysql_connector-2.2.9-cp36-cp36m-win_amd64.whl size=247952 sha256=90f20d5cc298034e1fbf
34fabd23a66c0cb2b25195e8fb81b10c663a04838b
Stored in directory: c:\users\administrator\appdata\local\pip\cache\wheels\d4\96\09\a2cbdf0079fa50f344bdff4fe9406f7cdb3b6fcbf1c1e5
64
Successfully built mysql-connector
Installing collected packages: mysql-connector
Successfully installed mysql-connector-2.2.9
通过SQLAlchemy连接数据库
连接数据库文件:
from sqlalchemy import create_engine
# 连接数据库
# 地址
HOST = "127.0.0.1"
# 数据库
DATABASE = "python_01"
# 端口
PORT = 3306
# 用户名,密码
USERNAME = "root"
PASSWORD = "root"
# 创建
# DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOST, PORT, DATABASE) # 这个版本会有个警告,也不影响使用
# dialect+driver://username:password@host:port/database?charset=utf8
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOST, PORT, DATABASE) # 官方推荐版本
# 创建数据库引擎
engine = create_engine(DB_URL)
# 创建连接
with engine.connect() as conn:
# 执行SQL语句,原生SQL语句
result = conn.execute("select * from classes") # 从python_01数据库中查找classes表中的数据
print(result)
# 查询一条数据
print(result.fetchone())
- 首先从sqlalchemy中导入create_engine,用这个函数来创建引擎;
- 然后用engine.connect()来连接数据库。其中一个比较重要的一点是,通过create_engine函数的时候,需要传递一个满足某种格式的字符串,对这个字符串的格式来进行解释。
即:
dialect+driver://username:password@host:port/database?charset=utf8
dialect是数据库的实现,比如MySQL、PostgreSQL、SQLite,并且转换成小写。driver是Python对应的驱动,如果不指定,会选择默认的驱动,比如MySQL的默认驱动是MySQLdb。username是连接数据库的用户名,password是连接数据库的密码,host是连接数据库的域名,port是数据库监听的端口号,database是连接哪个数据库的名字。
用SQLAlchemy执行原生SQL
我们将上一个例子中的数据库配置选项单独放在一个constants.py的文件中
from sqlalchemy import create_engine
from constants import DB_URI
#连接数据库
engine = create_engine(DB_URI,echo=True)
# 使用with语句连接数据库,如果发生异常会被捕获
with engine.connect() as con:
# 先删除users表
con.execute('drop table if exists authors')
# 创建一个users表,有自增长的id和name
con.execute('create table authors(id int primary key auto_increment,'name varchar(25))')
# 插入两条数据到表中
con.execute('insert into persons(name) values("abc")')
con.execute('insert into persons(name) values("xiaotuo")')
# 执行查询操作
results = con.execute('select * from persons')
# 从查找的结果中遍历
for result in results:
print(result)
在类中操作数据库的时候,我们可以将下面的映射到数据库中
- 类 --------->一张表
- 属性 ------->表字段
- 对象 ------->一条记录
class Users(object):
name = "xxxx"
pass
# 类 ------>一张表
# 属性 ------>表字段
# 对象 ------>一条记录
user = Users(1, "xxxx")
user.add()
4、SQLAlchemy-ORM介绍
ORM介绍
随着项目越来越大,采用原生SQL的方式在代码中会出现大量的SQL语句,对项目的进展非常不利:
- SQL语句重复利用率不高,越复杂的SQL语句条件越多,代码越长。会出现很多相近似的SQL语句
- 很多SQL语句是在业务逻辑中拼出来的,如果有数据库需要更改,就要去修改这些逻辑,很容易漏掉某些SQL语句的修改
- 写SQL时容易忽略web安全问题
ORM: Object Relationship Mapping,对象关系映射,通过ORM我们可以通过类的方式去操作数据库,而不用写原生的SQL语句。通过把表映射成类,把行作为实例,把字段作为属性,ORM在执行对象操作时候最终还是会把对应的操作转换为数据库原生语句。
使用ORM的优点:
- 易用性:使用ORM做数据库的开发可以有效的减少SQL语句,写出来的模型也更加直观;
- 性能损耗小;
- 设计灵活:可以轻松写出来复杂的查询;
- 可移植性:SQLAlchemy封装了底层的数据库实现,支持多个关系型数据库,包括MySQL,SQLite。
5、使用SQLAlchemy
要使用ORM来操作数据库,首先需要创建一个类来与对应的表进行映射。现在以User表来做为例子,它有自增长的id、name、fullname、password这些字段,那么对应的类为:
下面的使用ORM操作数据库模板是固定的,必须有这些步骤:
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
# 连接数据库
# 地址
HOST = "127.0.0.1"
# 数据库
DATABASE = "sys"
# 端口
PORT = 3306
# 用户名,密码
USERNAME = "root"
PASSWORD = "root"
# dialect+driver://username:password@host:port/database?charset=utf8
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOST, PORT, DATABASE) # 官方推荐版本
# 创建数据库引擎
engine = create_engine(DB_URL)
# 引擎连接 绑定 # 都要继承这个函数生成的基类
base = declarative_base(engine)
# ORM操作数据库
class Users(base):
# 数据库中操作表的名字, 定义表的名字
__tablename__ = 'students'
# 创建表的字段
id = Column(Integer, primary_key=True, autoincrement=True) # Column(数据类型,primary_key=主键,autoincrement=自增)
name = Column(String(50), nullable=False) # Column(数据类型,String(50)不超过50字符,nullable=False非空)
gender = Column(Integer, default=1, comment="1代表男性,2代表女性") # Column(数据类型,default=默认,comment=备注解释)
# 模型映射到数据库中
base.metadata.create_all()
SQLAlchemy会自动的设置第一个Integer的主键并且没有被标记为外键的字段添加自增长的属性。
创建完和表映射的类后,还需要映射到数据库当中,执行以下代码将类映射到数据库中:
# 模型映射到数据库中
base.metadata.create_all()