Flask中sqlalchemy模块的实例用法


当前第2页 返回上一页

模型的构造函数,接收的参数是使用关键字参数指定的模型属性初始值。注意,role 属性也可使用,虽然他不是真正的数据库列,但却是一对多关系的高级表示。这些新建对象的 id 属性并没有明确设定,因为主键是由 Flask-SQLAlchemy 管理的。现在这些对象只存在于 Python 解释器中,尚未写入数据库。

>> from myflask import db, User, Role
>> db.create_all()
>> admin_role = Role(name="Admin")
>> mod_role = Role(name="Moderator")
>> user_role = Role(name="User")
>> user_john = User(username="john", role=admin_role)
>> user_susan = User(username="susan", role=mod_role)
>> user_david = User(username="david", role=user_role)
>> admin_role.name
'Admin'
>> admin_role.id
None
---------
>> db.session.add_all([admin_role, mod_role, user_role, user_john, user_susan, user_david])  # 把对象添加到会话中.
>> db.session.commit()      # 把对象写入数据库, 使用 commit() 提交会话.

(3)修改行

>> admin_role = "Administrator"
>> db.session.add(admin_role)
>> db.session.commit()

(4)删除行

>> db.session.delete(mod_role)
>> db.session.commit()

(5)查询行

Flask-SQLAlchemy 为每个模型类都提供了 query 对象.

获取表中的所有记录

>> Role.query.all()
  [<Role u'Admin'>, <Role u'Moderator'>, <Role u'User'>]
>> User.query.all()
  [<Role u'john'>, <Role u'susan'>, <Role u'david'>]

查询过滤器

filter_by() 等过滤器在 query 对象上调用, 返回一个更精确的 query 对象. 多个过滤器可以一起调用, 直到获取到所需的结果.

>> User.query.filter_by(role=user_role).all()   # 以列表形式,返回所有结果,
>> User.query.filter_by(role=user_role).first() # 返回结果中的第一个.

filter() 对查询结果过滤,比”filter_by()”方法更强大,参数是布尔表达式

# WHERE age<20
users = User.query.filter(User.age<20)
# WHERE name LIKE 'J%' AND age<20
users = User.query.filter(User.name.startswith('J'), User.age<20)

查询过滤器 :

查询执行函数 :

first_or_404() | 返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应 | |

| get() | 返回指定主键对应的行,如果没有对应的行,则返回 None |

get_or_404() | 返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 | |错误响应

| count() | 返回查询结果的数量 |

| paginate() | 返回一个 Paginate 对象,它包含指定范围内的结果 |

(6)会话管理,事务管理

单个提交

>> db.session.add(ONE)
>> db.session.commit()

多个提交

>> db.session.add_all([LIST_OF_MEMBER])
>> db.session.commit()

删除会话

>> db.session.delete(mod_role)
>> db.session.commit()

事务回滚 : 添加到数据库会话中的所有对象都会还原到他们在数据库时的状态.

>> db.session.rollback()

七、视图函数中操作数据库

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        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
        session["name"] = form.name.data
        form.name.data = ""             # why empty it ?
        return redirect(url_for("index"))
    return render_template("index.html", current_time=datetime.utcnow(), form=form, name=session.get("name"), 
    known=session.get("known"))

八、分页对象 Pagination

1. paginate() 方法

paginate() 方法的返回值是一个 Pagination 类对象,该类在 Flask-SQLAlchemy 中定义,用于在模板中生成分页链接。

paginate(页数[,per_page=20, error_out=True])
    页数 : 唯一必须指定的参数,
    per_page : 指定每页现实的记录数量, 默认 20.
    error_out : True 如果请求的页数超出了返回, 返回 404 错误; False 页数超出范围时返回一个,空列表.

示例代码:

@main.route("/", methods=["GET", "POST"])
def index():
    # ...
    page = request.args.get('page', 1, type=int)    # 渲染的页数, 默认第一页, type=int 保证参数无法转换成整数时, 
    返回默认值.
    pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=current_app.config
    ["FLASKY_POSTS_PER_PAGE"], error_out=False)
    posts = pagination.items
    return render_template('index.html', form=form, posts=posts,pagination=pagination)

2. 分页对象的属性及方法:

Flask_SQLAlchemy 分页对象的属性:

在分页对象可调用的方法:

3. 在模板中与 BootStrap 结合使用示例

使用 Flaks-SQLAlchemy 的分页对象与 Bootstrap 中的分页 CSS, 可以轻松的构造出一个 分页导航.

分页模板宏 _macros.html : 创建一个 Bootstrap 分页元素, 即一个有特殊样式的无序列表.

{% macro pagination_widget(pagination,endpoint) %}
<ul class="pagination">
    <li {% if not pagination.has_prev %} class="disabled" {% endif %}>
        <a href="{% if pagination.has_prev %}{{url_for(endpoint, page=paginatin.page - 1, **kwargs)}}{% else %}
        #{% endif %}">
            &laquo;
        </a>
    </li>
    {% for p in pagination,.iter_pages() %}
        {% if p %}
            {% if p == pagination.page %}
            <li class="active">
                <a  rel="external nofollow" >{{p}}</a>
            </li>
            {% else %}
            <li>
                <a  rel="external nofollow" >{{p}}</a>
            </li>
            {% endif %}
        {% else %}
        <li class="disabled"><a  rel="external nofollow" >&hellip;</a> </li>
        {% endif %}
    {% endfor %}
    <li {% if not pagination.has_next %} class="disabled" {% endif%}>
        <a href="{% if paginatin.has_next %}{{ url_for(endpoint, page=pagination.page+1, **kwargs) }}{% else %}
        #{% endif %}">
            &raquo;
        </a>
    </li>
</ul>
{% endmacro %}

导入使用分页导航

{% extends "base.html" %}
{% import "_macros.html" as macros %}
...
<div class="pagination">
    {{ macro.pagination_widget(pagination, ".index")}}
</div>

九、监听事件

1. set 事件

示例代码 :

from markdown import markdown
import bleach
class Post(db.Model):
    # ...
    body = db.Colume(db.Text)
    body_html = db.Column(db.Text)
    # ...
    @staticmethod
    def on_changeed_body(target, value, oldvalue, initiator):
        allowed_tags = ["a", "abbr", "acronym", "b", "blockquote", "code", "em",
                        "i", "li", "ol", "pre", "strong", "ul", "h1", "h2","h3","h4","p"]
        target.body_html = bleach.linkify(bleach.clean(markdown(value, output_format="html"), tags=allowed_tags, 
        strip=True))
db.event.listen(Post.body, "set", Post.on_changeed_body) 
# on_changed_body 函数注册在 body 字段上, 是 SQLIAlchemy "set" 事件的监听程序, 
# 这意味着只要这个类实例的 body 字段设了新值, 函数就会自动被调用. 
# on_changed_body 函数把 body 字段中的文本渲染成 HTML 格式, 
# 结果保存在 body_html 中, 自动高效的完成 Markdown 文本到 HTML 的转换

十、记录慢查询

十一、Binds 操作多个数据库

十二、其他

1. ORM 在查询时做初始化操作

当 SQLIAlchemy ORM 从数据库查询数据时, 默认不调用__init__ 方法, 其底层实现了 Python 类的 __new__() 方法, 直接实现 对象实例化, 而不是通过 __init__ 来实例化对象.

如果需要在查询时, 依旧希望实现一些初始化操作, 可以使用 orm.reconstructor() 装饰器或 实现 InstanceEvents.load() 监听事件。

# orm.reconstructor
from sqlalchemy import orm
class MyMappedClass(object):
    def __init__(self, data):
        self.data = data
        # we need stuff on all instances, but not in the database.
        self.stuff = []
    @orm.reconstructor
    def init_on_load(self):
        self.stuff = []
# InstanceEvents.load()
from sqlalchemy import event
## standard decorator style
@event.listens_for(SomeClass, 'load')
def receive_load(target, context):
    "listen for the 'load' event"
    # ... (event handling logic) ...

如果只是希望在从数据库查询生成的对象中包含某些属性, 也可以使用 property 实现:

class AwsRegions(db.Model):
    name=db.Column(db.String(64))
    ...
    @property
    def zabbix_api(self):
        return ZabbixObj(zabbix_url)
    @zabbix_api.setter
    def zabbix_api(self):
        raise ValueError("zabbix can not be setted!")

到此这篇关于Flask中sqlalchemy模块的实例用法的文章就介绍到这了,更多相关Flask中sqlalchemy模块的使用内容请搜索


标签:SQLite

返回前面的内容

相关阅读 >>

from csv to Sqlite3 by python 导入csv到Sqlite实例

基于python分析你的上网行为 看看你平时上网都在干嘛

c#操作Sqlite数据库方法小结

scp远程vps快速搬家和wdcp升级php5.3安装memcached和eaccelerator教程

android实现搜索功能并将搜索结果保存到Sqlite中(实例代码)

android Sqlite基本用法详解

关于centos 7下Sqlite3找不到的问题解决

详解python中executemany和序列的使用方法

golang连接sqlx库的操作使用指南

python 操作Sqlite数据库详情

更多相关阅读请进入《Sqlite》频道 >>


数据库系统概念 第6版
书籍

数据库系统概念 第6版

机械工业出版社

本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...