![22e52856f45ac95f17d7665e87be7464.png](https://i-blog.csdnimg.cn/blog_migrate/a97f4b1f1be876f311597b563e5bc275.jpeg)
这个项目的全部目录在这里
在上一篇文章里,我们搭建好了最最基本的首页,现在让我们来实现用户登录,注册的环节。
首先,在开始前,我们需要一个数据库。这里我选择的是MySQL数据库,具体可以从这篇博客里进行配置(他使用的是Windows系统,如果是Mac的话也是差不多的,就是跳过了安装Visual Studio的步骤)。
配置好数据库后,我们需要连接它。这里我也是费了好久才配置好,用的是PyMysql。首先,让我们来创建一个数据库。打开mysql终端,输入:
CREATE
把其中的<database-name>替换成你自己的数据库名称,然后关闭MySQL终端,在命令行里输入
pip install flask-sqlalchemy
来安装SQLAlchemy。然后,在extensions.py中实例化它:
from
现在如果运行程序,可能会发现有几个警告,不过那是因为我们还没有设置数据库呢。现在让我们就来设置。先打开命令行,输入
pip install pymysql
来安装pymysql。安装完之后,在app文件夹里创建config.py,来存放所有的设置。在config.py里输入:
import
现在,我们就可以在init.py中引入它了:
import os
from flask import Flask # 导入Flask
from .extensions import * # 导入已经实例化了的扩展
from app.config import config # 导入config
def create_app():
app = Flask(__name__) # 创建app实例
app.config.from_object(config[os.environ.get('FLASK_ENV')]) # 设置从config中导入设置
# ...
return app # 返回app
但是这还不行,因为在config.py中,我们使用了2个环境变量,所以我们需要先定义他们,再运行程序。但是这样太太麻烦了,因为环境变量只在当前会话中有用。但是,我们可以用python-dotenv来简化。首先,安装它:
pip install python-dotenv
然后,再在根目录下创建一个.env文件,来存放环境变量:
FLASK_APP=app.py
DEV_DATABASE_PASS=<database-password>
DEV_DATABASE_NAME=<database-name>
把<database-password>和<database-name>替换成你的数据库密码和名称就好了。现在我们再运行程序,应该一切都跟以前一样,因为我们还没有创建表。现在在app下创建models.py,来存放数据库模型:
from .extensions import db # 导入SQLAlchemy
class User(db.Model): # User类继承自db.Model
__tablename__ = 'users' # 定义表名
id = db.Column(db.Integer, primary_key=True) # 定义id,并且为主键
username = db.Column(db.String(64)) # 用户名
email = db.Column(db.String(128)) # 邮箱地址
def __repr__(self): # 定义User类的返回名称
return '<User %s>' % self.username # 返回 <User 用户名>
类创建好了,现在我们要更新数据库了。我这里用的是flask-migrate来管理版本。
pip install flask-migrate
初始化:
# app/extensions.py
# app/__init__.py
# ...
def create_app():
app = Flask(__name__) # 创建app实例
app.config.from_object(config[os.environ.get('FLASK_ENV')]) # 设置从config中导入设置
# 初始化扩展
# ...
migrate.init_app(app, db)
# ...
return app # 返回app
现在,我们来初始化flask-migrate:
flask db init
这时,出现了错误:
Traceback (most recent call last):
File "/Users/sam/Desktop/Python/AttributeError/venv/bin/flask", line 10, in <module>
sys.exit(main())
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/flask/cli.py", line 966, in main
cli.main(prog_name="python -m flask" if as_module else None)
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/flask/cli.py", line 586, in main
return super(FlaskGroup, self).main(*args, **kwargs)
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/click/decorators.py", line 21, in new_func
return f(get_current_context(), *args, **kwargs)
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/flask/cli.py", line 425, in decorator
with __ctx.ensure_object(ScriptInfo).load_app().app_context():
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/flask/cli.py", line 388, in load_app
app = locate_app(self, import_name, name)
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/flask/cli.py", line 257, in locate_app
return find_best_app(script_info, module)
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/flask/cli.py", line 83, in find_best_app
app = call_factory(script_info, app_factory)
File "/Users/sam/Desktop/Python/AttributeError/venv/lib/python3.8/site-packages/flask/cli.py", line 119, in call_factory
return app_factory()
File "/Users/sam/Desktop/Python/AttributeError/app/__init__.py", line 12, in create_app
app.config.from_object(config[os.environ.get('FLASK_ENV')]) # 设置从config中导入设置
KeyError: None
这需要我们更改一处代码:
# app/__init__.py
这里,我们设置如果FLASK_ENV是None,就从default导入。现在再初始化:
flask db init
就不会报错了。应该会在根目录下创建一个名为migrations的文件夹,用来存储数据库模型的改动。现在,来升级数据库:
flask db migrate
会出现「No changes in schema detected.」。原因是flask-migrate是从文件的import来判断是否出现改动的,而我们没有在任何文件里引入models.py。现在,在app中创建auth文件夹,并创建__init__.py:
# app/auth/__init__.py
from flask import Blueprint
auth = Blueprint('auth', __name__)
from . import views
然后,创建views.py:
# app/auth/views.py
from . import auth
from app.models import User
然后,注册auth蓝本:
# app/__init__.py
# ...
def create_app():
app = Flask(__name__) # 创建app实例
# ...
from .main import main as main_bp # 导入蓝图
app.register_blueprint(main_bp) # 注册蓝图到应用
from .auth import auth as auth_bp
app.register_blueprint(auth_bp)
return app # 返回app
现在再执行flask db migrate,就可以正常生成更新文件了。要想让这个文件生效,需要升级数据库:
flask db upgrade
现在,让我们来测试一下数据库,使用flask shell来打开flask的交互式shell:
Python
你可能会发现,现在的模型中,所有的用户都是平等的,没有管理员。现在,让我们来解决这个问题:
# app/models.py
from .extensions import db # 导入SQLAlchemy
class Role(db.Model):
__tablename__ = 'role'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
users = db.relationship('User', backref='role', lazy='dynamic') # 创建一个关联
def __repr__(self):
return '<Role %s>' % self.name
class User(db.Model): # User类继承自db.Model
__tablename__ = 'users' # 定义表名
id = db.Column(db.Integer, primary_key=True) # 定义id,并且为主键
username = db.Column(db.String(64)) # 用户名
email = db.Column(db.String(128)) # 邮箱地址
role_id = db.Column(db.Integer, db.ForeignKey('role.id'))
def __repr__(self): # 定义User类的返回名称
return '<User %s>' % self.username # 返回 <User 用户名>
我们来更新数据库:
"Added role"
INFO
现在在flask shell中测试一下:
Python
好了,今天就先写到这里吧。我已经把代码放到了GitHub上,你可以git checkout ef00826来查出这个版本,注意要新建.env文件,填入环境变量,并且执行flask db upgrade来升级数据库。
写在最后
这是这个系列的第2篇文章,因为我也是一个小白,所以如果哪里有误还请大神多多指教