数据库(二)操作数据库

在shell中操作数据库

C:\Users\Geek Lee\Geek-Lee.github.io>venv\Scripts\activate

(venv) C:\Users\Geek Lee\Geek-Lee.github.io>python hello.py shell
#进入shell中
C:\Users\GEEKLE~1\GEEK-L~1.IO\venv\lib\site-packages\flask_sqlalchemy\__init__.p
y:800: UserWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and
 will be disabled by default in the future.  Set it to True to suppress this war
ning.
  warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and wi
ll be disabled by default in the future.  Set it to True to suppress this warnin
g.')
>>> from hello import db  
###从hello中导入db
>>> db.create_all()
###新建一个数据文件data.sqlite文件,文件名是配置中指定的
>>> db.drop_all()###删除和新建数据库
>>> db.create_all()
>>> from hello import Role,User
###从hello导入模型
>>> 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=user_role)
>>> user_david = User(username='david',role=user_role)
###创建角色和用户
###模型的构造函数接受的参数是使用关键字参数指定的模型属性初始值。
###注意,role属性也可使用,虽然他不是真正的数据库列,但却是一对多关系的高级表示。
###前面讲了role属性虽在Role模型,但却是User属性,是User的角色标签,也在User中设置。
>>> print(admin_role.id)
None
>>> print(mod_role.id)
None
>>> print(user_role.id)
None
>>>db.session.add_all([admin_role,mod_role,user_role,user_john,user_susan,user_david])
>>> db.session.commit()
>>> print(admin_role.id)
1
>>> print(mod_role.id)
2
>>> print(user_role.id)
3
###id是进入数据库后sqlalchemy自动分配的,没进入之前时不分配id的。像git一样先创建,再add到db.session数据库会话中,最后提交cmmit。才能进入数据库。
>>> admin_role.name = 'Administrator'
>>> db.session.add(admin_role)
>>> db.session.commit()
###修改数据库
>>> db.session.delete(mod_role)
>>> db.session.commit()
###删除行
>>> Role.query.all()
[<Role 'Administrator'>, <Role 'User'>]
>>> User.query.all()
[<User 'john'>, <User 'susan'>, <User 'david'>]
###查询行
>>> User.query.filter_by(role=user_role).all()
[<User 'susan'>, <User 'david'>]
###通过User类的role属性查询
>>> str(User.query.filter_by(role=user_role))
'SELECT users.id AS users_id, users.username AS users_username, users.role_id AS
 users_role_id \nFROM users \nWHERE :param_1 = users.role_id'
>>> user_role = Role.query.filter_by(name='User').first()
>>> user_role
<Role 'User'>
###通过Role类的name属性查询

关系和查询的处理方式类似,下面这个例子分别从关系的两端查询角色和用户之间的一对多关系:

>>> users = user_role.users
###user_role(name属性为“User”的Role实例)的users属性可以查询User实例
>>>users
[<User u'susan'>,<USer u'david'>]###自动执行查询
>>> users
<sqlalchemy.orm.dynamic.AppenderBaseQuery object at 0x0000000004081C50> ###现在可能改进了不能自动执行查询
>>> users[0].role
<Role 'User'>
###users变量所代表列表的第一个User实例的role属性可以查询到Role实例(也就是他的角色类型)

这些功能的执行完成归功了以下语句:

class Role(db.Model):      ###定义模型
    ...
    users = db.relationship('User', backref='role')

Role的user属性可以查到User (外面的一对可以查询括号里面的)
User的role属性也可以反向查到Role (backref,括号里面的一对可以查backref)


不多上面的user_role.users查询有个小问题,就是执行user_role.users表达式是隐含的查询会自动的调用all()返回一个用户列表,而且query对象是隐藏的,因此无法指定更精确的查询过滤器。修改模型里面的关系设置,加入了lazy=‘dynamic’参数,从而禁止自动执行查询。
改进后的hello.py如下:

class Role(db.Model):      ###定义模型
    ...
    users = db.relationship('User', backref='role',lazy='dynamic')

再次使用查询,区别如下:

>>> users = user_role.users
###user_role(name属性为“User”的Role实例)的users属性可以查询User实例
>>>users
[<User u'susan'>,<USer u'david'>]###没改进时自动执行查询得到结果
>>> users
<sqlalchemy.orm.dynamic.AppenderBaseQuery object at 0x0000000004081C50> ###现在改进了不能自动执行查询

改进后user_role.users返回一个尚未执行的查询,需在上面添加过滤器才能执行结果:

>>> user_role.users.order_by(User.username).all()
[<User 'david'>, <User 'susan'>]
>>> user_role.users.count()
2

在视图函数中操作数据库

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()###实例化表格
    if form.validate_on_submit():###如果表格里面提交了文字
        user = User.query.filter_by(username=form.name.data).first()
        ###用过滤器过滤username等于表格的提交的名字,如果没有返回None,否则返回查询的第一个结果
        if user is None:
        ###user=None执行下面的语句
            user = User(username=form.name.data)
            ###创建一个User类的实例
            db.session.add(user)
            ###添加到db.session数据库会话中,配置中设置了自动提交所以不用commit了
            session['known'] = False
            ###保存在用户会话session(请求上下文,字典),键'known'的值设置为False
        else:
        ###否则执行下面的语句
            session['known'] = True
            ###保存在用户会话session(请求上下文,字典),键'known'的值设置为True
        session['name'] = form.name.data
        ###表中的name保存为用户会话session的键'name'的值
        form.name.data = ''
        ###表中数据清空
        return redirect(url_for('index'))
        ###重定向到index,重定向不经过if直接执行下一语句return
    return render_template('index.html',
        form = form, name=session.get('name'),
        known=session.get('known', False))
    ###返回模板index.html,form表格实例传入form变量,
    ###name变量值从session会话中获取,
    ###known变量从session会话的键'known'获取值,上文如果没设置默认为False

模板index.html

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}GeekLee{% endblock %}

{% block page_content %}
<div class="page-header">
    <h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!</h1>
    {% if not known %}###########if not False显示下面的
    <p>Pleased to meet you!</p>#########
    {% else %}########否则显示下面的
    <p>Happy to see you again!</p>################
    {% endif %}#############
</div>
{{ wtf.quick_form(form) }}
{% endblock %}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值