python - Flask- 数据库

数据库的设置

Web应用中普遍使用的是关系模型的数据库,关系型数据库把所有的数据都存储在表中,表用来给应用的实体建模,表的列数是固定的,行数是可变的。它使用结构化的查询语言。关系型数据库的列定义了表中表示的实体的数据属性。比如:商品表里有name、price、number等。 Flask本身不限定数据库的选择,你可以选择SQL或NOSQL的任何一种。也可以选择更方便的SQLALchemy,类似于Django的ORM。SQLALchemy实际上是对数据库的抽象,让开发者不用直接和数据库打交道,而是通过Python对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升。

SQLALchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。flask-sqlalchemy是一个简化了SQLALchemy操作的flask扩展。

安装

pip install flask-sqlalchemy

使用Flask-SQLAlchemy管理数据库

在Flask-SQLAlchemy中,数据库使用URL指定,而且程序使用的数据库必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI键中。

对比下Django和Flask中的数据库设置:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':'dailyfresh',
        'HOST':'localhost',
        'PORT':'3306',
        'USER':'root',
        'PASSWORD':'mysql',
    }
}

Flask的数据库设置:

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test3'

常用的SQLAlchemy字段类型
常用的SQLAlchemy字段类型
常用的SQLAlchemy列选项
常用的SQLAlchemy列选项
常用的SQLAlchemy关系选项
常用的SQLAlchemy关系选项

定义模型

模型表示程序使用的数据实体,使用SQLAlchemy中,模型一般是Python类,必须继承自db.Model,db是SQLAlchemy类的实例,代表程序使用的数据库。

类中的属性对应数据库表中的列。id为主键,是由Flask-SQLAlchemy管理。db.Column类构造函数的第一个参数是数据库列和模型属性类型。

#coding=utf-8
from flask import Flask,render_template,redirect,url_for
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test1'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

#实例化SQLAlchemy对象
db = SQLAlchemy(app)

#定义模型类-作者
class Author(db.Model):
    __tablename__ = 'author'
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32),unique=True)
    email = db.Column(db.String(64))
    au_book = db.relationship('Book',backref='author')
    def __str__(self):
        return 'Author:%s' %self.name

#定义模型类-书名
class Book(db.Model):
    __tablename__ = 'books'
    id = db.Column(db.Integer,primary_key=True)
    info = db.Column(db.String(32),unique=True)
    lead = db.Column(db.String(32))
    au_book = db.Column(db.Integer,db.ForeignKey('author.id'))
    def __str__(self):
        return 'Book:%s,%s'%(self.info,self.lead)
#默认访问首页查询所有作者和书名
@app.route('/')
def index():
    author = Author.query.all()
    book = Book.query.all()
    return render_template('index.html',author=author,book=book)

#添加作者
@app.route('/append_author')
def append():
    au_di = Author(name='帝国上将',email='diguo@163.com')
    db.session.add(au_di)
    db.session.commit()
    return redirect(url_for('index'))

#添加书名
@app.route('/append_book')
def append_book():
    bk_di = Book(info='仙佛录',lead='杨天行')
    db.session.add(bk_di)
    db.session.commit()
    return redirect(url_for('index'))

#删除作者
@app.route('/delete_author<int:id>')
def delete_author(id):
    db1 = Author.query.filter_by(id=id).first()
    db.session.delete(db1)
    return redirect(url_for('index'))

#删除书名
@app.route('/delete_book<int:id>')
def delete_book(id):
    db1 = Book.query.filter_by(id=id).first()
    db.session.delete(db1)
    return redirect(url_for('index'))


if __name__ == '__main__':
    db.drop_all()
    db.create_all()
    #生成数据
    au_xi = Author(name='我吃西红柿',email='xihongshi@163.com')
    au_qian = Author(name='萧潜',email='xiaoqian@126.com')
    au_san = Author(name='唐家三少',email='sanshao@163.com')
    bk_xi = Book(info='吞噬星空',lead='罗峰')
    bk_xi2 = Book(info='寸芒',lead='李杨')
    bk_qian = Book(info='飘渺之旅',lead='李强')
    bk_san = Book(info='冰火魔厨',lead='融念冰')
    #把数据提交给用户会话
    db.session.add_all([au_xi,au_qian,au_san,bk_xi,bk_xi2,bk_qian,bk_san])
    #提交会话
    db.session.commit()
    app.run(debug=True)

模板页面示例:

  <h1>玄幻系列</h1>
    <a href="/append_author">增加作者</a>
    <ul>
        <li>{% for x in author %}</li>
        <li>{{ x }}</li><a href="/delete_author{{ x.id }}">删除</a>
        <li>{% endfor %}</li>
    </ul>
    <hr>
     <a href="/append_book">增加书籍</a>
    <ul>
        <li>{% for y in book %}</li>
        <li>{{ y }}</li><a href="/delete_book{{ y.id }}">删除</a>
        <li>{% endfor %}</li>
    </ul>

数据库基本操作

在Flask-SQLAlchemy中,插入、修改、删除操作,均由数据库会话管理。会话用db.session表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用commit()方法提交会话。

在Flask-SQLAlchemy中,查询操作是通过query对象操作数据。最基本的查询是返回表中所有数据,可以通过过滤器进行更精确的数据库查询。

将数据添加到会话中示例:

user = User(name='python')
db.session.add(user)
db.session.commit()

在视图函数中定义模型类

#coding=utf-8
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

#设置连接数据库的URL
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/Flask_test'

#设置每次请求结束后会自动提交数据库中的改动
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)

class Role(db.Model):
    # 定义表名
    __tablename__ = 'roles'
    # 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    user = db.relationship('User', backref='role')

    #repr()方法显示一个可读字符串
    def __repr__(self):
        return 'Role:'.format(self.name)

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, index=True)
    pswd = db.Column(db.String(64))
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    def __repr__(self):
        return 'User:'.format(self.username)


if __name__ == '__main__':
    db.drop_all()
    db.create_all()

常用的SQLAlchemy查询过滤器
常用的SQLAlchemy查询过滤器
常用的SQLAlchemy查询执行器
常用的SQLAlchemy查询执行器

创建表:

db.create_all()

删除表

db.drop_all()

插入一条数据

In [7]: us = User(name='wang',email='wang@163.com',pswd='123456')
In [8]: db.session.add(us)
In [9]: db.session.commit()

插入多条数据

In [14]: us2 = User(name='zhang',email='zhang@163.com',pswd='201512')
In [15]: us3 = User(name='chen',email='chen@163.com',pswd='987654')
In [16]: us4 = User(name='zhou',email='zhou@163.com',pswd='456789')
In [17]: db.session.add_all([us2,us3,us4])
In [18]: db.session.commit()

查询:filter_by精确查询

返回名字等于wang的所有人

user = User.query.filter_by(name='wang').all()
print user
print user.id

first()返回查询到的第一个对象

user = User.query.first()
print user

all()返回查询到的所有对象

User.query.all()

filter模糊查询,返回名字结尾字符为e的所有数据。

User.query.filter(User.name.endswith('e')).all()

get(),参数为主键,如果主键不存在没有返回内容

User.query.get()

逻辑非,返回名字不等于zhou的所有数据。

user = User.query.filter(User.name!='zhou').all()
print user

逻辑与,需要导入and,返回and()条件满足的所有数据。

from sqlalchemy import and_
user = User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()
print user

逻辑或,需要导入or_

from sqlalchemy import or_
user = User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).first()
print user

not_ 相当于取反

from sqlalchemy import not_
user = User.query.filter(not_(User.name=='wang')).all()
print user

查询数据后删除

user = User.query.first()
db.session.delete(user)
db.session.commit()
User.query.all()

更新数据

user = User.query.first()
user.name = 'dong'
db.session.commit()
User.query.first()

数据库迁移

在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库。最直接的方式就是删除旧表,但这样会丢失数据。

更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化,然后把变动应用到数据库中。

在Flask中可以使用Flask-Migrate扩展,来实现数据迁移。并且集成到Flask-Script中,所有操作通过命令就能完成。

为了导出数据库迁移命令,Flask-Migrate提供了一个MigrateCommand类,可以附加到flask-script的manager对象上。

首先要在虚拟环境中安装Flask-Migrate。

pip install flask-migrate

创建迁移仓库

#这个命令会创建migrations文件夹,所有迁移文件都放在里面。
python database.py db init

创建迁移脚本

自动创建迁移脚本有两个函数,upgrade()函数把迁移中的改动应用到数据库中。downgrade()函数则将改动删除。自动创建的迁移脚本会根据模型定义和数据库当前状态的差异,生成upgrade()和downgrade()函数的内容。对比不一定完全正确,有可能会遗漏一些细节,需要进行检查

#创建自动迁移脚本
python database.py db migrate -m 'initial migration'

更新数据库

python database.py db upgrade
#coding=utf-8
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate,MigrateCommand
from flask_script import Shell,Manager

app = Flask(__name__)
manager = Manager(app)

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/Flask_test'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
migrate = Migrate(app,db) 
manager.add_command('db',MigrateCommand)

#定义模型Role
class Role(db.Model):
    # 定义表名
    __tablename__ = 'roles'
    # 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    user = db.relationship('User', backref='role')

    #repr()方法显示一个可读字符串,
    def __repr__(self):
        return 'Role:'.format(self.name)

#定义用户
class User(db.Model):
    __talbe__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    #设置外键
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    def __repr__(self):
        return 'User:'.format(self.username)


if __name__ == '__main__':
    #创建表
    db.create_all()

    #给Role模型添加数据
    admin_role = Role(name='Administer')
    user_role = Role(name='User')

    #给User模型添加数据
    user_zhangsan = User(username='zhangsan', role=admin_role)
    user_lisi = User(username='lisi', role=user_role)
    user_wangwu = User(username='wangwu', role=user_role)
    user_zhaoliu = User(username='zhaoliu', role=user_role)

    #提交数据
    db.session.add_all([admin_role,user_role, user_zhangsan, user_lisi, user_wangwu, user_zhaoliu])

    db.session.commit()
    manager.run()

Flask—Mail

在开发过程中,很多应用程序都需要通过邮件提醒用户,Flask的扩展包Flask-Mail通过包装了Python内置的smtplib包,可以用在Flask程序中发送邮件。

Flask-Mail连接到简单邮件协议(Simple Mail Transfer Protocol,SMTP)服务器,并把邮件交给服务器发送。

如下示例,通过开启QQ邮箱SMTP服务设置,发送邮件。

from flask import Flask
from flask_mail import Mail, Message

app = Flask(__name__)
#配置邮件:服务器/端口/传输层安全协议/邮箱名/密码
app.config.update(
    DEBUG = True,
    MAIL_SERVER='smtp.qq.com',
    MAIL_PROT=465,
    MAIL_USE_TLS = True,
    MAIL_USERNAME = '371673381@qq.com',
    MAIL_PASSWORD = 'goyubxohbtzfbidd',
)

mail = Mail(app)

@app.route('/')
def index():
 # sender 发送方,recipients 接收方列表
    msg = Message("This is a test ",sender='371673381@qq.com', recipients=['shengjun@itcast.cn','371673381@qq.com'])
    #邮件内容
    msg.body = "Flask test mail"
    #发送邮件
    mail.send(msg)
    print "Mail sent"
    return "Sent Succeed"

if __name__ == "__main__":
    app.run()
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值