本文为沐码小站开源服务端程序运行和部署说明,项目代码地址:https://github.com/wintc23/blog-backend。
运行项目需要做一些准备工作,包括运行环境的安装、邮箱SMTP服务开启以及第三方服务的申请等。
其中邮箱和第三方服务的信息等敏感信息,不能直接写在源码中,我们可以将其导入系统环境变量,应用程序从环境变量中获取这些信息。
可以在blog-backend文件夹同级创建一个env.sh脚本文件来导入环境变量,该文件不需要加入版本库。
(注:文中导入env.sh的环境变量均为测试创建或者随意打的字符串,应该都没我自己的敏感信息😃)
一、运行环境安装
1.安装python3(不兼容python2)
2.安装mysql 8 (5.7应该也可以运行)
需要注意几个点:
- mysql字符集最好设置为utf8mb4,utf8mb4可以支持emoji表情(比如:😜)。
- 需要开启允许博客后台程序运行的主机远程连接mysql服务。(数据库对外开启3306端口并不太安全,可以设置为仅允许特定ip连接)
对于开发环境和生产环境,需要创建不同的数据库,将数据库地址和用户名密码等写入env.sh:
# 开发环境数据库信息, 注意替换host、port、usernmae、passwd、databasename
export DEV_DATABASE_URL=mysql+pymysql://username:passwd@host:port/databasename?charset=utf8mb4
# 生产环境数据库信息
export DATABASE_URL=mysql+pymysql://username:passwd@host:port/databasename?charset=utf8mb4
二、开启邮箱SMTP服务
通知用户或者管理员,需要使用到邮件发送服务。一般邮箱都提供了开启SMTP服务的功能,以QQ邮箱为例:
开启服务后,点击生成授权码获取到一个类似秘钥的授权码,专门用于第三方登录。邮箱相关的信息要导入环境变量,所以需要写入env.sh:
# 邮箱地址
export MAIL_USERNAME=xxx@qq.com
# 邮箱授权码
export MAIL_PASSWORD=apasswordgeneratebyqq
# 邮件发送人
export MAIL_SENDER=Muma<xxx@qq.com>
# 邮件主题前缀
export MAIL_SUBJECT_PREFIX=[沐码小站]
因为我是使用QQ邮箱,所以在代码config.py中写了固定的QQ邮件服务器和端口,同时启用了SSL协议:
你可以根据自己的邮箱情况来修改这三个值。
三、第三方服务申请
博客后台使用的第三方服务有:七牛云文件上传、github/QQ登录、algolia搜索服务。要直接使用代码中的这些功能,需要先在第三方平台申请服务。
1. 七牛云对象存储申请
该服务用于存储博客中的图片。如果使用该服务,需要一个已经通过ICP备案的域名。七牛可以分配一个临时的域名,但是存在有效期。
注册七牛云账号登录后,在七牛云对象存储新建空间,并进行域名绑定。地址:https://portal.qiniu.com/kodo/bucket。
域名绑定可以填入二级域名,域名绑定后需要将该域名通过CNAME记录解析到七牛给定的地址:
现在可以在刚才新建的空间里上传文件了,也可以通过我们自己的域名或者七牛的临时域名访问到文件了。但是对于博客程序,我们在编辑博客的时候会使用API进行上传,上传时需要用到七牛的Access Key和Secret Key,可以在密钥管理里获取。
将域名、空间名、Access Key、Secret Key写入env.sh文件:
export QI_NIU_ACCESS_KEY=xxxxxxxxx # access key
export QI_NIU_SECRET_KEY=xxxxxxxxx # secret key
export DEV_QI_NIU_BUCKET=blog_dev_img # 空间名 开发环境
export QI_NIU_BUCKET=blog_img # 空间名 生产环境
export DEV_QI_NIU_LINK_URL=https://devfile.wintc.top # 开发环境绑定的域名
export QI_NIU_LINK_URL=https://file.wintc.top # 生产环境绑定的域名
这里开发环境和生产环境申请了不同的空间。如果只想申请一个,也可以将生产环境、开发环境的空间名、域名设置为相同。
2.github OAuth第三方登录
在github的开发者设置OAuth Apps里注册一个应用,获取Client ID和Client secrets用于github登录。地址:https://github.com/settings/developers。
点击new OAuth App申请应用:
填写应用信息,应用名和Homepage随意填写,应用名会在用户登录的时候展示给用户。最重要的是权限验证回调URL,这里填写前端github登录的地址:http://域名/login。比如开发环境: http://127.0.0.1:8000/login,生产环境:https://wintc.top/login。
填写完成后,在应用信息里可以得到Client ID和Client secrets:
同样的,针对开发环境和生产环境可以分别申请2个应用,并把Client ID和Client secrets写到脚本中:
export FLASK_GITHUB_CLIENT_ID=23a4b61b9678ed2c9da # Client ID 生产环境
export DEV_FLASK_GITHUB_CLIENT_ID=3sde5accfa4aeddf1a15 # Client ID 开发环境
export FLASK_GITHUB_SECRET=a9ce5bb062fda2138110f23d72b14e23419375c # Secrets 生产环境
export DEV_FLASK_GITHUB_SECRET=46a5b3f49a14aeef38e127232140be90e65811eb # Secrets 开发环境
3. QQ互联第三方登录
为了让用户可以通过QQ进行登录,与github类似,需要在QQ互联申请一个网站应用。地址:https://connect.qq.com/manage.html。
创建网站应用,填写应用信息,同样需要填写一个回调域名,不过与github不同的是,QQ互联可以填写多个回调域,因此可以不区分开发环境和生产环境,单独申请一个应用即可:
然后会得到一个APP ID和APP Key:
同样写入env.sh:
export FLASK_QQ_CLIENT_ID=1018432345
export FLASK_QQ_SECRET=c3a1ef8c4441646bfxxxxxxxxxxxxxx
4. algolia搜索服务
使algolia搜索服务方便文章查询,我们会把公开的文章以json格式提交到algolia的数据中心,然后调用API进行搜索,检索到相应文章。同样的需要在algolia官网申请APP ID和API调用凭证。algolia官网地址:https://www.algolia.com。
在官网注册后登录后填写一些个人信息,填写完成后选择一个数据中心,可以选离我们最近的香港。
完成后会默认创建一个应用,可以直接使用这个应用。按照指引创建一个Index,这里的Index的作用是为了区分应用中的数据集,比如我们可以用两个个Index分别存储开发数据库和生产数据库中的文章。
我们这里创建了一个开发环境的Index(名为”dev_article“),然后在Indices菜单中再创建一个用于生产环境的Index,Index的名字在API中会用到,同样需要导入到系统环境变量中。
对于每个应用,会有一个APP ID,一个用于查询的Search-Only API Key和用于操作数据的Admin API Key。其中用于查询的Key可以写在前端,用于管理数据的key需要和其它信息一起导入环境变量,先写入env.sh中:
export ALGOLIA_APP_ID=PH934V0BY7 # APP ID
export ALGOLIA_ADMIN_API_KEY=6a5d6e8e3aa164e8a6c23089edc971d # APP Admin Key
export DEV_ALGOLIA_INDEX=article_dev # 开发环境下的搜索索引
export ALGOLIA_INDEX=article_prod # 生产环境下的搜索索引
至此,必要的准备工作大都完成了。不过我们还需要在env.sh中导入一些其它的变量。
四、其它环境变量
export SECRET_KEY=xxxx # 对称加密秘钥,任意字符串,用于加密/解密用户token
export FLASK_ADMIN=lushg-tcxg@qq.com # 管理员邮箱,用于接收用户通知等信息
export FLASK_POSTS_PER_PAGE=10 # 每页展示的文章数量
export FLASK_BBS_PER_PAGE=10 # 留言分页每页展示数量
export DOMAIN=https://wintc.top # 部署域名,邮件通知用户链接中会用到
export DEV_DOMAIN=http://127.0.0.1:8000 # 部署域名————开发环境,邮件通知用户链接中会用到
export FLASK_CONFIG=development # 配置环境,development为开发环境,production为正式环境
其中FLASK_CONFIG用于控制前述环境变量使用开发环境还是生产环境值,在本地开发时设置为development,服务器发布时设置为production。
五、项目运行
1. 创建虚拟环境并激活
cd blog-backend
python3 -m venv venvname # 创建 venvname取你喜欢的名字
source venvname/bin/activate # 激活
2.安装依赖
pip install -r requirement.txt
3.数据库
我们安装完mysql后,创建了两个数据库。需要对库进行初始化,创建各个数据表结构。应用程序通过ORM来操作数据库,而不需要直接写sql语句。ORM使得操作数据库非常便捷,app/models.py是需要创建的数据库表对应的Model类。
- 数据库初始化:第一次初始化数据库,会在本地创建数据库操作历史相关的文件夹,类似git仓库的.git文件。
python3 main.py db init
- 后续修改了model之后,提交一个数据库版本,会修改项目目录下的数据库版本文件,这一步不会改动到数据库的表结构。
python3 main.py db migrate -m "some msg"
- 将修改提交到数据库,这一步才会真正影响我们数据库的表结构。
python main.py db upgrade
4. 插入默认数据
默认需要向角色表、文章类型表中插入数据。
$ python3 main.py shell
>>> Role.insert_roles()
>>> PostType.insert_types()
5. 设置管理员
为了能发布文章,我们需要一个真正的管理员用户,可以通过QQ或者github登录,登录后在shell把该用户改为管理员权限。登录成功后,在数据库中找到刚刚登录的用户,这里我们假设第一个登录用户为管理员,可以按照:
$ python3 main.py shell
>>> role = Role.query.filter_by(name = 'Administrator').first()
>>> user = User.query.first()
>>> user.role = role;
>>> db.session.add(user);
>>> db.session.commit()
6. 开发环境初始数据写入
我们需要向数据库写入一些初始数据,比如角色(用于控制权限)、文章分类、初始管理员账号等。app/models.py编辑插入的初始数据。
如果在开发环境,为方便测试,我们可能需要一些初始化的文章、评论、留言等数据。app/models.py中的各个Model提供了数据插入的静态方法,可以启动应用程序交互式shell,并执行指令即可插入测试数据。自动生成用户、文章、评论、点赞、留言:
$ python3 main.py shell
>>> User.generate_fake()
>>> Post.generate_fake()
>>> Comment.generate_fake()
>>> Like.generate_fake()
>>> Message.generate_fake()
上述指令往角色表、用户表、文章类型表分别插入了一些默认记录,数据生成函数可在代码查看。
7. 启动项目
gunicorn --worker-class eventlet -w 1 -b:5000 main:app