1.Flask-SQLAlchemy
Flask-SQLAlchemy是一个Flask扩展,简化了Flask程序中使用SQLAlchemy的操作。SQLAlchemy是一个很强大的关系型数据库框架,支持多种数据库后台,提供了高层ORM,也提供了使用数据库原生SQL的低层功能。
安装:
pip install flask-sqlalchemy
数据库URL必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI键中。
hello.py:配置数据库
basedir=os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI']=\
'sqlite:///'+os.path.join(basedir,'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True #每次请求结束后都会自动提交数据库中的变化
db=SQLAlchemy(app)
2.定义模型
ORM中,模型一般是一个Python类,类中的属性对应数据库表中的列。
hello.py:定义Role和User模型
class Role(db.Model):
__tablename__='roles'
id=db.Column(db.Integer,primary_key=True)
name=db.Column(db.String(64),unique=True)
def __repr__(self):
return '<Role %r>' % self.name
class User(db.Model):
__tablename__='users'
id=db.Column(db.Integer,primary_key=True)
username=db.Column(db.String(64),unique=True,index=True)
def __repr__(self):
return '<User %r>' % self.username
3.关系
角色到用户的一对多关系,因为一个角色可属于多个用户,而每个用户都只能有一个角色。
class Role(db.Model):
#...
users=db.relationship('User',backref='role') #backref参数向User模型中添加一个role属性,从而定义反向关系,这一属性可替代role_id访问Role模型,此时获取的是模型对象,而不是外键的值。如果无法决定外键,就要为db.relationship()提供额外参数,从而确定所用外键。
class User(db.Model):
#...
role_id=db.Column(db.Integer,db.ForeignKey('roles.id'))
4.在视图函数中操作数据库
hello.py
user=User.query.filter_by(username=form.name.data).first()
if user is None:
user=User(username=form.name.data)
db.session.add(user)
session['known']=False
else:
session['known']=True
#...
return render_template('index.html',form=form,name=session.get('name'),known=session.get('known',False),current_time=datetime.utcnow())
index.html
{%if not known%}
<p>Pleased to meet you!</p>
{%else%}
<p>Happy to see you again!</p>
{%endif%}
5.Flask-Migrate实现数据库迁移
pip install flask-migrate
hello.py:配置Flask-Migrate
from flask_migrate import Migrate,MigrateCommand
#...
migrate=Migrate(app,db)
manager.add_command('db',MigrateCommand)
在维护数据库迁移之前,要使用init子命令创建迁移仓库:
python hello.py db init
upgrade()函数把迁移中的改动应用到数据库中,downgrade()函数则将改动删除。
python hello.py db upgrade
运行应用程序使用Flask-SQLAlchemy时得到一下警告:
SADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True or False to suppress this warning.
‘SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and ‘
改正:
app.config[‘SQLALCHEMY_TRACK_MODIFICATIONS’] = False
6.Flask-Mail
pip install flask-mail
hello.py:配置Flask-Mail使用Gmail
import os
#...
app.config['MAIL_SERVER']='smtp.googlemail.com'
app.config['MAIL_PORT']=587
app.config['MAIL_USE_TLS']=True
app.config['MAIL_USERNAME']=os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD']=os.environ.get('MAIL_PASSWORD')
千万不要把账户密令直接写入脚本,特别是当你计划开源自己的作品时,为了保护账户信息,要让脚本从环境中导入敏感信息。
hello.py:初始化Flask-Mail
from flask_mail import Mail
#...
mail=Mail(app)
在环境中设定用户名和密码两个环境变量
export MAIL_USERNAME=’username’
export MAIL_PASSWORD=’password’
发送电子邮件时遇到错误:
python通过SMTP发送邮件失败:
错误1:smtplib.SMTPAuthenticationError: (550, b’User has no permission’)
我们使用python发送邮件时相当于自定义客户端根据用户名和密码登录,然后使用SMTP服务发送邮件,新注册的163邮箱是默认不开启客户端授权的(对指定的邮箱大师客户端默认开启),因此登录总是被拒绝,解决办法(以163邮箱为例):进入163邮箱-设置-客户端授权密码-开启(授权码是用于登录第三方邮件客户端的专用密码)
Gmail:
If you have activated two-step verification, you need to turn that off. Also ,you can try another thing. Go to https://www.google.com/settings/security/lesssecureapps and https://myaccount.google.com/security?pli=1#connectedapps, allow access for the less secure app. Google might consider your server’s sign-in process as less secure sign-in technology, which makes your account more vulnerable. So allowing access might help you.