[ZHUAN]Flask学习记录之Flask-SQLAlchemy
From: http://www.cnblogs.com/agmcs/p/4445583.html
各种查询方式:http://www.360doc.com/content/12/0608/11/9369336_216812259.shtml
Flask-SQLAlchemy库让flask更方便的使用SQLALchemy,是一个强大的关系形数据库框架,既可以使用orm方式操作数据库,也可以使用原始的SQL命令.
Flask-Migrate 是一个数据迁移框架,需要通过Flask-script库来操作.
一.配置Flask-SQLAlchemy
程序使用的数据库地址需要配置在SQLALCHEMY_DATABASE_URI中,SQLALchemy支持多种数据库,配置格式如下:
Postgres:
postgresql://scott:tiger@localhost/mydatabase
MySQL:
mysql://scott:tiger@localhost/mydatabase
Oracle:
oracle://scott:tiger@127.0.0.1:1521/sidname
SQLite:
sqlite:////absolute/path/to/foo.db
db是SQLALchemy类的实例,表示程序使用的数据库,为用户提供Flask-SQLALchemy的所有功能

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__)
#配置数据库地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
#该配置为True,则每次请求结束都会自动commit数据库的变动
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
db = SQLAlchemy(app)
#也可以db = SQLAlchemy() db.init_app(app)

二.定义模型
Flask-SQLALchemy使用继承至db.Model的类来定义模型,如:

class User(db.Model, UserMixin):#UserMixin是Flask-Login库中所需要的
__tablename__ = 'users'
#每个属性定义一个字段
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(64),unique=True)
password = db.Column(db.String(64))
def __repr__(self):
return '<User %r>' % self.username

定义完需要在Python Shell中导入db,调用db.create_all()来创建数据库
(1)常用字段选项:
primary_key 设置主键
unique 是否唯一
index 是否创建索引
nullable 是否允许为空
default 设置默认值,可以传入函数的引用 如传入 datetime.datetime.utcnow 则每次创建时时间都是最新时间
三.增删查改
(1) 插入数据:

from app.models import User
from app import db #创建一个新用户
u = User()
u.username = 'abc'
u.password = 'abc'
#将用户添加到数据库会话中
db.session.add(u)
#将数据库会话中的变动提交到数据库中,如果不Commit,数据库中是没有改动的
db.commit()

(2)查找数据:

#返回所有用户保存到list中
user_list = User.query.all() #查找username为abc的第一个用户,返回用户实例
u = User.query.filter_by(username='abc').first() #模糊查找用户名以c结尾的所有用户
user_list = User.query.filter(username.endswith('c')).all() #查找用户名不是abc的用户
u = User.query.filter(username != 'abc').first()

(3)删除数据:
user = User.query.first()
db.session.delete(user)
db.session.commit()
(4)修改数据:
u = User.query.first()
u.username = 'sb'
db.session.commit()
四.一对多关系
我的理解是:在多的一边定义外键,而relathonship()函数是用来建立关系的,可以只在一边定义,也可以两边都使用(只在一边使用时加上了backref选项等同于两边都使用)

class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
#backref将在Address表中创建个名为persons的Person引用,之后可以使用address.persons访问这个地址的所有人
addresses = db.relationship('Address', backref='persons',
lazy='dynamic') class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(50))
#在多的一边使用db.ForeignKey声明外键
person_id = db.Column(db.Integer, db.ForeignKey('person.id'))

五.多对多关系
多对多关系可以分解为原表和关联表之间两个多对一关系,如下代码建立了学生与所选课程之间的关系:

#创建关联表,两个字段的外键是另两个表,一个学生对应多个关联表,一个关联表对应多个课程
registrations = db.Table('registrations',
db.Column('student_id',db.Integer,db.ForeignKey('students.id')),
db.Column('class_id',db.Integer,db.ForeignKey('classes.id'))
) class Student(db.Model):
__tablename__ = 'students'
id = db.Column(db.Integer,primary_key=True,)
name = db.Column(db.String)
classes = db.relationship('Class',
secondary = registrations, #关联表,只需要在一个表建立关系,sqlalchemy会负责处理好另一个表
backref = db.backref('students',lazy='dynamic'),
lazy = 'dynamic') class Class(db.Model):
__tablename__ = 'classes'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)

多对多的使用:

#学生1增加一门选课
student1.classes.append(class1)
#学生1退选class1
student1.classes.remove(class1)
#学生1所选课程,由于指定了lazy='dynamic'所以没有直接返回列表,而需要使用.all()
student1.classes.all()

六.分页导航
Flask-SQLALchemy的Pagination对象可以方便的进行分页,
对一个查询对象调用pagenate(page, per_page=20, error_out=True)函数可以得到pagination对象,第一个参数表示当前页,第二个参数代表每页显示的数 量,error_out=True的情况下如果指定页没有内容将出现404错误,否则返回空的列表

#从get方法中取得页码
page = request.args.get('page', 1, type = int)
#获取pagination对象
pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=10, error_out = False) #pagination对象的items方法返回当前页的内容列表
posts = pagination.items

pagination对象常用方法:
has_next :是否还有下一页
has_prev :是否还有上一页
items : 返回当前页的所有内容
next(error_out=False) : 返回下一页的Pagination对象
prev(error_out=False) : 返回上一页的Pagination对象
page : 当前页的页码(从1开始)
pages : 总页数
per_page : 每页显示的数量
prev_num : 上一页页码数
next_num :下一页页码数
query :返回 创建这个Pagination对象的查询对象
total :查询返回的记录总数
iter_pages(left_edge=2, left_current=2, right_current=5, right_edge=2)
在模版中使用

{% macro render_pagination(pagination, endpoint) %}
<div class=pagination>
{%- for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
<a href="{{ url_for(endpoint, page=page) }}">{{ page }}</a>
{% else %}
<strong>{{ page }}</strong>
{% endif %}
{% else %}
<span class=ellipsis>…</span>
{% endif %}
{%- endfor %}
</div>
{% endmacro %}

七.事件监听
Flask-SQLALchemy不但提供了方便的数据库操作,还提供了事件的监听,如下
from sqlalchemy import event def my_append_listener(target, value, initiator):
print "received append event for target: %s" % target event.listen(MyClass.collection, 'append', my_append_listener)
Listeners have the option to return a possibly modified version of the value, when the retval=Trueflag is passed to listen():
def validate_phone(target, value, oldvalue, initiator):
"Strip non-numeric characters from a phone number" return re.sub(r'(?![0-9])', '', value) # setup listener on UserContact.phone attribute, instructing
# it to use the return value
listen(UserContact.phone, 'set', validate_phone, retval=True)
A validation function like the above can also raise an exception such as ValueError to halt the operation.
Several modifiers are available to the listen() function.
| Parameters: |
|
|---|
- append(target, value, initiator)
-
Receive a collection append event.
Parameters: - target – the object instance receiving the event. If the listener is registered with raw=True, this will be the InstanceState object.
- value – the value being appended. If this listener is registered withretval=True, the listener function must return this value, or a new value which replaces it.
- initiator – the attribute implementation object which initiated this event.
Returns: if the event was registered with retval=True, the given value, or a new effective value, should be returned.
- remove(target, value, initiator)
-
Receive a collection remove event.
Parameters: - target – the object instance receiving the event. If the listener is registered with raw=True, this will be the InstanceState object.
- value – the value being removed.
- initiator – the attribute implementation object which initiated this event.
Returns: No return value is defined for this event.
- set(target, value, oldvalue, initiator)
-
Receive a scalar set event.
Parameters: - target – the object instance receiving the event. If the listener is registered with raw=True, this will be the InstanceState object.
- value – the value being set. If this listener is registered with retval=True, the listener function must return this value, or a new value which replaces it.
- oldvalue – the previous value being replaced. This may also be the symbol NEVER_SET or NO_VALUE. If the listener is registered withactive_history=True, the previous value of the attribute will be loaded from the database if the existing value is currently unloaded or expired.
- initiator – the attribute implementation object which initiated this event.
Returns: if the event was registered with retval=True, the given value, or a new effective value, should be returned.
[ZHUAN]Flask学习记录之Flask-SQLAlchemy的更多相关文章
- Flask学习记录之Flask-SQLAlchemy
Flask-SQLAlchemy库让flask更方便的使用SQLALchemy,是一个强大的关系形数据库框架,既可以使用orm方式操作数据库,也可以使用原始的SQL命令. Flask-Migrate ...
- Flask学习记录之Flask-Migrate
一.配置Flask-Migrate from flask.ext.migrate import Migrate, MigrateCommand migrate = Migrate(app,db) #第 ...
- Flask学习记录之Flask-Login
Flask-Loging 可以方便的管理用户会话,保护路由只让认证用户访问 http://flask-login.readthedocs.org/en/latest/ 一.初始化Flask-Login ...
- Flask学习记录之Flask-Admin
相信用过Django框架的都不会忘记它强大的Admin功能,Flask-admin是一款能够与Django Admin所媲美的扩展,能够快速创建Web管理界面,实现了用户.文件增删改查等常用功能:也可 ...
- Flask学习记录之MarkDown编辑文本
为了让网页支持markdown编辑文本,使用如下了4个库 PageDown : 在前端提供一个可以实时将markdown内容转换成html文本进行效果预览的编辑器 Flask-PageDown: 这个 ...
- Flask学习记录之Flask-WTF
Flask-wtf时Wtforms库的flask框架扩展,能够方便的处理Web表单 一.定义一个web表单 使用flask-wtf时,每个web表单都由一个继承自flask.ext.wtf.Form的 ...
- Flask学习记录之Flask-Moment
Moment.js 是一个简单易用的轻量级JavaScript日期处理类库,提供了日期格式化.日期解析等功能.它支持在浏览器和NodeJS两种环境中运行.此类库能够 将给定的任意日期转换成多种不同的格 ...
- Flask学习记录之Flask-Mail
Flask-Mail可以连接到配置中的SMTP服务器,进行邮件发送,如果没有进行SMTP服务器的配置,将会默认连接到localhost上的 一.配置及初始化 (1)flask应用配置 #配置选项 MA ...
- Flask学习记录之使用Werkzeug散列密码
数据库中直接存放明文密码是很危险的,Werkzeug库中的security能够方便的实现散列密码的计算 security库中 generate_password_hash(password,metho ...
随机推荐
- openstack 启用spice
Openstack启用spice协议 #控制节点 #安装 ? 1 apt-get install nova-spiceproxy spice-html5 spice-vdagent #配置 nano ...
- 某返利网站admin目录index.php文件混淆加密算法分析
---恢复内容开始--- 文件已经加密,可以在此下载:index.php 文件内容打开大概如此: 简单字符替换之后,发现字符串用base64_decode仍无法解码. 找到一个解码网站:找源码 解码后 ...
- 20169210《Linux内核原理与分析》第一周作业
第一次接触Linux,还是有点不适应的,与Windows区别还是比较大的.在免费与收费.软件与支持.安全性.使用习惯.可定制性和应用范畴等方面都有区别. 通过实验楼的<Linux基础入门(新版) ...
- android中listview的一些样式设置
在Android中,ListView是最常用的一个控件,在做UI设计的时候,很多人希望能够改变一下它的背景,使他能够符合整体的UI设计,改变背景背很简单只需要准备一张图片然后指定属性 android: ...
- Excel VBA批量修改文件夹下的文件名
今天,有同事提出想批量修改文件名,规则比较简单,在第五位后加“-”即可, 上网没找到相关工具,就自己做了个excel,用宏代码修改. 代码如下: Private Sub CommandButton1_ ...
- [转] CSS transition
https://css-tricks.com/almanac/properties/t/transition/ The transition property is a shorthand prope ...
- android反编译经验谈
反编译这事,找对了工具其实非常简单. 反编译工具下载地址http://pan.baidu.com/s/1eQvshwu android的反编译要经过两个步骤: 1.把dex文件转为jar 2.jar转 ...
- JS 拼凑字符串
和Java一样,JS中直接用"+"号拼凑字符串是很耗费资源的,所以在大量拼凑字符串的情景中,我们也需要一个类似于StringBuffer的工具, 下面利用Array.join()方 ...
- poj 1821 Fence 单调队列优化dp
/* poj 1821 n*n*m 暴力*/ #include<iostream> #include<cstdio> #include<cstring> #incl ...
- php+正则将字符串中的字母数字和中文分割
原文出处 如果一段字符串中出现字母数字还有中文混排的情况,怎么才能将他们区分开呢,经过一番思索,得到了如下代码,分享给大家 如:$str="php如何将字 符串中322的字母数字sf f45 ...