上一篇:我用Python写网站《二》
欢迎来我的论坛讨论Python搭建博客网站的问题和经验。www.ahoh.club。
本系列所有文章都会同步到这里,如果不想关注博主,就来这里阅读吧!
通过本文,你应该掌握:
Flask项目框架插件配置Flask注册 项目布局 写在前面
不阅读前两篇,不耽误学习本文内容。
上一篇已经在我的Ahoh项目中加入了Flask-SQLAlchemy插件,并且可以利用Flask Shell实现Mysql的增、删、改、查操作。
在拥有了数据库的加持之后,我接下了就会加速内容的输出了。
不过,在真正开干之前,还有一步非常重要,就是项目布局调整,一个好的布局是项目最重要的开端。
一个最简单的Flask应用可以是单个文件,但是当项目越来越大的时候,把所有代码放在单个文件中就有点不堪重负了。Python项目使用包来管理代码,把代码分为不同的模块,然后在需要的地方导入模块,本文也会按这一方式管理代码。
应用设置先来看看我们现在项目的布局。
ahoh/├── app.py # 项目app模块├── migrations # 数据库版本文件夹└── venv # Python虚拟环境
当前项目的总体布局实际上是没有什么问题的,主要问题在于app模块是单个的文件,里面集成了太多的东西。
由于Python还支持文件夹作为一个模块,所以我们应该把app.py模块换成文件夹模块,如果不理解这里也没有关系,开干就完事了。
以解决问题为导向!!
我希望在项目根目录下应该有以下元素:
app/ ,包含应用所有代码的Python包tests/ ,包含测试模块的文件夹venv/ ,Python虚拟环境(现在已经有了)版本控制配置,(.gitignore文件)项目需要的其他文件(配置文件)
第一步,在项目根目录(我这里是~/ahoh)下创建文件夹,命名app,然后将app.py移动到app文件夹下,并改名为__init__.py,指令如下:
~/ahoh$ mkdir app # 创建app文件夹~/ahoh$ mv app.py app/__init__.py # 移动app.py并改名
虽然代码做了更改,其实项目现在还是可以正常运行的,不过需要先激活虚拟环境。
然后,使用应用工厂函数代替之前的全局变量app,修改__init__.py如下(之前的代码可以先注释掉):
from flask import Flask# 应用工厂函数def create_app(): app = Flask(__name__) return app
然后使用Blueprint拆分视图函数,通常情况下,用户和博客是博客系统最主要的两个实体。
我们就用两个独立的文件分别处理用户相关的视图和博客相关的视图。
在app文件夹下创建auth.py和blog.py,分别编辑其中的内容如下:
# ~/ahoh/app/auth.py 用户蓝图from flask import Blueprintbp = Blueprint('auth',__name__,url_prefix='/auth')@bp.route('/login',methods=['GET','POST'])def login(): return 'login'@bp.route('/register',methods=['GET','POST'])def register(): return 'register'
# ~/ahoh/app/blog.py 博客蓝图from flask import Blueprint# 使用/访问博客蓝图bp = Blueprint('blog',__name__,url_prefix='/')@bp.route('/')def index(): return 'index'@bp.route('/detail/
然后在__init__.py中注册蓝图,在create_app()函数中添加如下代码:
from 、import blog,auth # Python 讲究随用随定义,这句可以直接写函数里app.register_blueprint(blog.bp)app.register_blueprint(auth.bp)
做完这些之后,蓝图就配置好了,之后的代码里,所有和用户相关的视图都放在auth.py里,其他就放在blog.py里面,如果随着功能扩展,有新的重要实体,还可以再新建一个模块。
先测试一下改装是否成功,使用flask run启动服务,然后在浏览器中输入localhost:5000/auth/login,或者输入localhost:5000/试试有什么效果吧!
然后就是重新配置Flask-SQLAlchemy和Flask-Migrate插件,我这里准备单独用一个模块管理这些插件。
首先,在app文件夹下创建exts.py,然后编辑代码如下:
# ~/ahoh/app/exts.py 插件模块from flask_sqlalchemy import SQLAlchemyfrom flask_migrate import Migratedb = SQLAlchemy()migrate = Migrate()
然后,在__init__.py中的create_app()函数中插入以下代码:
from .exts import db,migratedb.init_app(app)migrate.init_app(app,db)
这样,两个插件也就准备好了,接下来是配置文件,在app文件夹下创建settings.py,编辑内容如下:
class Default(object): SQLALCHEMY_DATAbase_URI='mysql+pymysql://root:_Why62345@localhost/ahoh?charset=utf8' SQLALCHEMY_TRACK_MODIFICATIONS = True SECRET_KEY='asl;nadflkgaasdfasyfgher' # 这里需要一个非常复杂的密码字符串class Development(Default): ENV='development' DEBUG=Trueclass Production(Default): ENV='production' DEBUG=False
然后,在__init__.py文件中的create_app()函数中,app=Flask(__name__)后,插入如下代码:
app.config.from_object(settings.Default)
这样,配置文件也搞定了。
后面就是模型的配置了,先在app文件夹下创建models.py文件,然后编辑内容如下:
from exts import dbfrom datetime import datetimeclass TimestampMixin(object): created = db.Column( db.DateTime, nullable=False, default=datetime.utcnow) updated = db.Column(db.DateTime, onupdate=datetime.utcnow) status = db.Column(db.Integer, default=0)class User(TimestampMixin, db.Model): __tablename__ = 't_users' id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True) password = db.Column(db.String(127), nullable=False) def __repr__(self): return '
这样我们的模型也就绪了,因为我这里把之前的数据全删掉了,所以还需要走一遍上一篇的创建流程,大家可以试试使用flask db migrate/upgrade能不能成功。
如果不能成功升级,直接删掉migrations文件夹,删掉数据库,重来。
想要在Flask Shell中使用db.create_all()创建所有对象,还需要在__init__.py中引入User。
from .models import User # 这句看起来没什么用,没有还真不行
下面再介绍一遍流程:
(venv)~/ahoh$ flask shell>>> from app.exts import db>>> db.create_all()
这样就可以创建表了
然后是,使用Flask-Migrate插件:
(venv)~/ahoh$ flask db init (venv)~/ahoh$ flask db migrate(venv)~/ahoh$ flask db upgrade
最后还要添加git管理的.gitignore文件,方便后面使用仓库。
在ahoh文件夹下创建git的版本控制文件.gitignore,然后把下面的内容贴进去:
venv/migrations/*.pyc__pycache__/instance/.pytest_cache/.coveragehtmlcov/dist/build/*.egg-info/
最后,把templates和static文件夹复制到app文件夹下,并在templates文件夹下创建auth和blog文件夹。
这样所有的项目设置就全部完成了,当前项目的结构:
ahoh/├── README.en.md├── README.md├── app│ ├── __init__.py│ ├── templates # 模板文件││├── auth # 用户页面││├── blog # 博客页面││└── bash.html # 模板基类│ ├── static # 静态文件││└── style.css # css文件 │ ├── auth.py# 用户蓝图│ ├── blog.py # 博客蓝图│ ├── exts.py # 插件模块│ ├── models.py # 模型模块│ └── settings.py # 默认设置├── migrations # 数据版本└── venv # 虚拟环境
这里还少了test文件夹,由于短时间内用不到,就先不搞了。
当前状态的代码保存到了Gitee仓库的quickstart分支。如果没有办法根据教程复现代码,可以直接从这个分支开始。
下面就要测试写一些功能,测试以下改版后的结构有没有问题。
用户注册首先就是用户注册视图(/register),修改视图函数代码如下:
@bp.route('/register', methods=['GET', 'POST'])def register(): print('regist') if request.method == 'POST': username = request.form['username'] password = request.form['password'] error = None if not username: error = '用户名不能为空' elif not password: error = '密码不能为空' elif User.query.filter_by(username=username).first() is not None: error = '用户 "{}" 已存在'.format(username) if error is None: u = User(username=username, password=generate_password_hash(password)) db.session.add(u) db.session.commit() return redirect(url_for('auth.login')) flash(error) return render_template('auth/register.html')
base.html内容如下:
{% block head %}
register.html内容如下:
{% extends 'base.html'%}{% block body_content %}{% endblock %}
然后,启动服务器,访问链接:http://localhost:5000/auth/register
可以看到如下界面:
然后填上数据,点击注册,如果没有错误的话就会跳转到登录页面,我在这里填了xiaoming和123456。
此时可以从数据库查到注册数据:
mysql> select * from t_users;+---------------------+---------+--------+----+----------+-------+--------------------------------------------------------------------------------------------------------+| created | updated | status | id | username | email | password |+---------------------+---------+--------+----+----------+-------+--------------------------------------------------------------------------------------------------------+| 2022-02-18 14:54:12 | NULL | 0 | 1 | xiaoming | NULL | pbkdf2:sha256:260000$RWe2k5pxwLUL4cjY$0fc8d3156599d3b5c36120e45c7404ce7085a8eca41d939cdc76d0b5e349de5f |+---------------------+---------+--------+----+----------+-------+--------------------------------------------------------------------------------------------------------+1 row in set (0.00 sec)
这样注册功能就成功啦,当前这个注册既没有字段验证,又没有错误提示,这些特性会在下一篇使用wtforms解决的!
写在最后 当前状态的代码保存到了Gitee仓库的quickstart分支。如果没有办法根据教程复现代码,可以直接从这个分支开始。
肝啊~~
欢迎来我的论坛讨论Python搭建博客网站的问题和经验。www.ahoh.club。
本系列所有文章都会同步到这里,如果不想关注博主,就来这里阅读吧!
下一篇:我用Python写网站《四》