时间:2021-07-01 10:21:17 帮助过:10人阅读
使用URL制定数据库
数据库引擎 | URL |
---|---|
MySQL | mysql://username:password@hostname/database |
Postgres | postgresql://username:password@hostname/database |
SQLite(Unix) | sqlite:////absolute/path/to/database |
SQLite(Windows) | sqlite:///c:/absolute/path/to/database |
SQLite 数 据 库 不 需 要 使 用 服 务 器, 因 此 不 用 指 定 hostname 、 username 和 password 。URL 中的 database 是硬盘上文件的文件名。
配置对象中还有一个很有用的选项,即 SQLALCHEMY_COMMIT_ON_TEARDOWN 键,将其设为 True时,每次请求结束后都会自动提交数据库中的变动
- <code class="language-python hljs has-numbering"><span class="hljs-keyword">from flask.ext.sqlalchemy <span class="hljs-keyword">import SQLAlchemy
- basedir = os.path.abspath(os.path.dirname(__file__))
- app = Flask(__name__)
- app.config[<span class="hljs-string">‘SQLALCHEMY_DATABASE_URI‘] =<span class="hljs-string">‘sqlite:///‘ + os.path.join(basedir, <span class="hljs-string">‘data.sqlite‘)
- app.config[<span class="hljs-string">‘SQLALCHEMY_COMMIT_ON_TEARDOWN‘] = <span class="hljs-keyword">True
- db = SQLAlchemy(app)</span></span></span></span></span></span></span></code>
- <code class="language-python hljs has-numbering"><span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">Role<span class="hljs-params">(db.Model):
- __tablename__ = <span class="hljs-string">‘roles‘<span class="hljs-comment">#__tablename__ 定义在数据库中使用的表名
- id = db.Column(db.Integer, primary_key=<span class="hljs-keyword">True)<span class="hljs-comment">#primary_key如果设为 True ,这列就是表的主键.如果没有定义 __tablename__ ,SQLAlchemy 会使用一个默认名字
- name = db.Column(db.String(<span class="hljs-number">64), unique=<span class="hljs-keyword">True)
- <span class="hljs-function"><span class="hljs-keyword">def <span class="hljs-title">__repr__<span class="hljs-params">(self):
- <span class="hljs-keyword">return <span class="hljs-string">‘<Role % r>‘ % self.name
- <span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">User<span class="hljs-params">(db.Model):
- __tablename__ = <span class="hljs-string">‘users‘
- id = db.Column(db.Integer, primary_key=<span class="hljs-keyword">True)
- username = db.Column(db.String(<span class="hljs-number">64), unique=<span class="hljs-keyword">True, index=<span class="hljs-keyword">True)
- <span class="hljs-function"><span class="hljs-keyword">def <span class="hljs-title">__repr__<span class="hljs-params">(self):
- <span class="hljs-keyword">return <span class="hljs-string">‘<User % r>‘ % self.username</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
__repr__&__str__
最常用的SQLAlchemy列类型
类型名 | Python类型 | 说 明 |
---|---|---|
Integer | int | 普通整数,一般是 32 位 |
SmallInteger | int | 取值范围小的整数,一般是 16 位 |
BigInteger | int 或 long | 不限制精度的整数 |
Float | float | 浮点数 |
Numeric | decimal.Decimal | 定点数 |
String | str | 变长字符串 |
Text | str | 变长字符串,对较长或不限长度的字符串做了优化 |
Unicode | unicode | 变长 Unicode 字符串 |
UnicodeText | unicode | 变长 Unicode 字符串,对较长或不限长度的字符串做了优化 |
Boolean | bool | 布尔值 |
Date | datetime.date | 日期 |
Time | datetime.time | 时间 |
DateTime | datetime.datetime | 日期和时间 |
Interval | datetime.timedelta | 时间间隔 |
Enum | str | 一组字符串 |
PickleType | 任何 Python 对象 | 自动使用 Pickle 序列化 |
LargeBinary | str | 二进制文件 |
最常使用的SQLAlchemy列选项
选项名 | 说 明 |
---|---|
primary_key | 如果设为 True ,这列就是表的主键 |
unique | 如果设为 True ,这列不允许出现重复的值 |
index | 如果设为 True ,为这列创建索引,提升查询效率 |
nullable | 如果设为 True ,这列允许使用空值;如果设为 False ,这列不允许使用空值 |
default | 为这列定义默认值 |
关系型数据库使用关系把不同表中的行联系起来。
- <code class="language-python hljs has-numbering"><span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">Role<span class="hljs-params">(db.Model):
- <span class="hljs-comment"># ...
- users = db.relationship(<span class="hljs-string">‘User‘, backref=<span class="hljs-string">‘role‘)<span class="hljs-comment">#添加到 Role 模型中的 users 属性代表这个关系的面向对象视角。对于一个 Role 类的实例,其 users 属性将返回与角色相关联的用户组成的列表。db.relationship() 的第一个参数表,如果模型类尚未定义,可使用字符串形式指定。db.relationship() 中的 backref 参数向 User 模型中添加一个 role 属性,从而定义反向关系。这一属性可替代 role_id 访问 Role 模型,此时获取的是模型对象
- <span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">User<span class="hljs-params">(db.Model):
- <span class="hljs-comment"># ...
- role_id = db.Column(db.Integer, db.ForeignKey(<span class="hljs-string">‘roles.id‘))<span class="hljs-comment">#关系使用 users 表中的外键连接了两行。添加到 User 模型中的 role_id 列被定义为外键,就是这个外键建立起了关系。传给 db.ForeignKey() 的参数 ‘roles.id‘ 表明,这列的值是 roles 表中行的 id 值。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
db.relationship() 都能自行找到关系中的外键,但有时却无法决定把哪一列作为外键。如果 User 模型中有两个或以上的列定义为 Role 模型的外键,SQLAlchemy 就不知道该使用哪列。如果无法决定外键,你就要为 db.relationship() 提供额外参数,从而确定所用外键
常用的SQLAlchemy关系选项
选项名 | 说 明 |
---|---|
backref | 在关系的另一个模型中添加反向引用 |
primaryjoin | 明确指定两个模型之间使用的联结条件。只在模棱两可的关系中需要指定 |
lazy | 指定如何加载相关记录。可选值有 select (首次访问时按需加载)、 immediate (源对象加载后就加载)、 joined (加载记录,但使用联结)、 subquery (立即加载,但使用子查询),noload (永不加载)和 dynamic (不加载记录,但提供加载记录的查询) |
uselist | 如果设为 Fales ,不使用列表,而使用标量值 |
order_by | 指定关系中记录的排序方式 |
secondary | 指定 多对多 关系中关系表的名字 |
secondaryjoin | SQLAlchemy 无法自行决定时,指定多对多关系中的二级联结条件 |
一对一
一对一关系可以用前面介绍的一对多关系表示,但调用 db.relationship() 时要把 uselist 设为 False ,把“多”变成“一”。
多对多
- <code class="language-python hljs has-numbering">tags = db.Table(<span class="hljs-string">‘tags‘,
- db.Column(<span class="hljs-string">‘tag_id‘, db.Integer, db.ForeignKey(<span class="hljs-string">‘tag.id‘)),
- db.Column(<span class="hljs-string">‘page_id‘, db.Integer, db.ForeignKey(<span class="hljs-string">‘page.id‘))
- )
- <span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">Page<span class="hljs-params">(db.Model):
- id = db.Column(db.Integer, primary_key=<span class="hljs-keyword">True)
- tags = db.relationship(<span class="hljs-string">‘Tag‘, secondary=tags,
- backref=db.backref(<span class="hljs-string">‘pages‘, lazy=<span class="hljs-string">‘dynamic‘))
- <span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">Tag<span class="hljs-params">(db.Model):
- id = db.Column(db.Integer, primary_key=<span class="hljs-keyword">True)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
- <code class="language-python hljs has-numbering">python hello.py shell
- <span class="hljs-prompt">>>> <span class="hljs-keyword">from hello <span class="hljs-keyword">import db
- <span class="hljs-prompt">>>> db.create_all()</span></span></span></span></code>
- <code class="language-python hljs has-numbering">db.drop_all()</code>
- <code class="language-python hljs has-numbering"><span class="hljs-comment">#创建对象,模型的构造函数接受的参数是使用关键字参数指定的模型属性初始值。
- admin_role = Role(name=<span class="hljs-string">‘Admin‘)
- user_role = Role(name=<span class="hljs-string">‘User‘)
- user_susan = User(username=<span class="hljs-string">‘susan‘, role=user_role)<span class="hljs-comment">#role 属性也可使用,虽然它不是真正的数据库列,但却是一对多关系的高级表示。
- user_john = User(username=<span class="hljs-string">‘john‘, role=admin_role)
- <span class="hljs-comment">#这些新建对象的 id 属性并没有明确设定,因为主键是由 Flask-SQLAlchemy 管理的。
- print(admin_role.id)<span class="hljs-comment">#None
- <span class="hljs-comment">#通过数据库会话管理对数据库所做的改动,在 Flask-SQLAlchemy 中,会话由 db.session 表示。
- <span class="hljs-comment">##首先,将对象添加到会话中
- db.session.add(admin_role)
- db.session.add(user_role)
- db.session.add(user_susan)
- db.session.add(user_john)
- <span class="hljs-comment">#简写:db.session.add_all([admin_role, user_role, user_john, user_susan])
- <span class="hljs-comment">##通过提交会话(事务),将对象写入数据库
- db.session.commit()</span></span></span></span></span></span></span></span></span></span></span></span></code>
会话提交:
数据库会话能保证数据库的一致性。提交操作使用原子方式把会话中的对象全部写入数据库。如果在写入会话的过程中发生了错误,整个会话都会失效。
数据库会话也可 回滚 。调用 db.session.rollback() 后,添加到数据库会话中的所有对象都会还原到它们在数据库时的状态。
- <code class="language-python hljs has-numbering">admin_role.name = <span class="hljs-string">‘Administrator‘
- db.session.add(admin_role)
- session.commit()</span></code>
- <code class="language-python hljs has-numbering">db.session.delete(mod_role)
- session.commit()</code>
查询行
- <code class="language-python hljs has-numbering">user_role = Role.query.filter_by(name=<span class="hljs-string">‘User‘).first()<span class="hljs-comment">#filter_by() 等过滤器在 query 对象上调用,返回一个更精确的 query 对象。</span></span></code>
常用过滤器
过滤器 | 说 明 |
---|---|
filter() | 把过滤器添加到原查询上,返回一个新查询 |
filter_by() | 把等值过滤器添加到原查询上,返回一个新查询 |
limit() | 使用指定的值限制原查询返回的结果数量,返回一个新查询 |
offset() | 偏移原查询返回的结果,返回一个新查询 |
order_by() | 根据指定条件对原查询结果进行排序,返回一个新查询 |
group_by() | 根据指定条件对原查询结果进行分组,返回一个新查询 |
最常使用的SQLAlchemy查询执行函数
方 法 | 说 明 |
---|---|
all() | 以列表形式返回查询的所有结果 |
first() | 返回查询的第一个结果,如果没有结果,则返回 None |
first_or_404() | 返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应 |
get() | 返回指定主键对应的行,如果没有对应的行,则返回 None |
get_or_404() | 返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 错误响应 |
count() | 返回查询结果的数量 |
paginate() | 返回一个 Paginate 对象,它包含指定范围内的结果 |
关系查询
- <code class="language-python hljs has-numbering">
- <span class="hljs-comment">#执行 user_role.users 表达式时,隐含的查询会调用 all() 返回一个用户列表。 query 对象是隐藏的,因此无法指定更精确的查询过滤器。
- users = user_role.users
- <span class="hljs-comment">#修改了关系的设置,加入了 lazy = ‘dynamic‘ 参数,从而禁止自动执行查询
- <span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">Role<span class="hljs-params">(db.Model):
- users = db.relationship(<span class="hljs-string">‘User‘, backref=<span class="hljs-string">‘role‘, lazy=<span class="hljs-string">‘dynamic‘)
- <span class="hljs-comment">#顺序排列
- user_role.users.order_by(User.username).all()</span></span></span></span></span></span></span></span></span></span></code>
- <code class="language-python hljs has-numbering"><span class="hljs-decorator">@app.route(‘/‘, methods=[‘GET‘, ‘POST‘])
- <span class="hljs-function"><span class="hljs-keyword">def <span class="hljs-title">index<span class="hljs-params">():
- form = NameForm()
- <span class="hljs-keyword">if form.validate_on_submit():
- user = User.query.filter_by(username=form.name.data).first()
- <span class="hljs-keyword">if user <span class="hljs-keyword">is <span class="hljs-keyword">None:
- user = User(username = form.name.data)
- db.session.add(user)
- session[<span class="hljs-string">‘known‘] = <span class="hljs-keyword">False
- <span class="hljs-keyword">else:
- session[<span class="hljs-string">‘known‘] = <span class="hljs-keyword">True
- session[<span class="hljs-string">‘name‘] = form.name.data
- form.name.data = <span class="hljs-string">‘‘
- <span class="hljs-keyword">return redirect(url_for(<span class="hljs-string">‘index‘))
- <span class="hljs-keyword">return render_template(<span class="hljs-string">‘index.html‘, form = form, name = session.get(<span class="hljs-string">‘name‘), known = session.get(<span class="hljs-string">‘known‘, <span class="hljs-keyword">False))</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
修改模板
- <code class="language-html hljs has-numbering">{ % extends "base.html" % }
- { % import "bootstrap/wtf.html" as wtf % }
- { % block title % }Flasky{ % endblock % }
- { % block page_content % }
- <span class="hljs-tag"><<span class="hljs-title">div <span class="hljs-attribute">class=<span class="hljs-value">"page-header">
- <span class="hljs-tag"><<span class="hljs-title">h1>Hello, { % if name % }{{ name }}{ % else % }Stranger{ % endif % }!<span class="hljs-tag"></<span class="hljs-title">h1>
- { % if not known % }
- <span class="hljs-tag"><<span class="hljs-title">p>Pleased to meet you!<span class="hljs-tag"></<span class="hljs-title">p>
- { % else % }
- <span class="hljs-tag"><<span class="hljs-title">p>Happy to see you again!<span class="hljs-tag"></<span class="hljs-title">p>
- { % endif % }
- <span class="hljs-tag"></<span class="hljs-title">div>
- {{ wtf.quick_form(form) }}
- { % endblock % }</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
让 Flask-Script 的 shell 命令自动导入特定的对象
- <code class="language-python hljs has-numbering"><span class="hljs-keyword">from flask.ext.script <span class="hljs-keyword">import Shell
- <span class="hljs-function"><span class="hljs-keyword">def <span class="hljs-title">make_shell_context<span class="hljs-params">():
- <span class="hljs-keyword">return dict(app=app, db=db, User=User, Role=Role)
- manager.add_command(<span class="hljs-string">"shell", Shell(make_context=make_shell_context))</span></span></span></span></span></span></span></span></code>
make_shell_context() 函数注册了程序、数据库实例以及模型,因此这些对象能直接导入 shell
- <code class="language-shell hljs cmake has-numbering">pip <span class="hljs-keyword">install flask-migrate</span></code>
- <code class="language-python hljs has-numbering"><span class="hljs-keyword">from flask.ext.migrate <span class="hljs-keyword">import Migrate, MigrateCommand
- <span class="hljs-comment"># ...
- migrate = Migrate(app, db)
- manager.add_command(<span class="hljs-string">‘db‘, MigrateCommand)</span></span></span></span></code>
- <code class="language-python hljs has-numbering">python hello.py db init</code>
- <code class="language-python hljs has-numbering">python hello.py db migrate -m <span class="hljs-string">"initial migration"</span></code>
- <code class="language-python hljs has-numbering">python hello.py db upgrade</code>
原文连接:http://blog.csdn.net/sun_dragon/article/details/51719753
flask学习笔记(-操作数据库)
标签:binary 会话 排序 csdn 定时 指定 建表 框架 replace