2019-06-09Flask第四集

Flask之数据库

SQL数据库

关系型数据库把数据存储在表中,表的列数是固定的,行数是可变的。


列定义表所表示的实体的数据属性,行定义各列对应的真实数据。


表中有个特殊的列,称为主键,它的值为表中各行的唯一标识符。


表中还可以有称为外键的列,引用同一个表或不同表中某行的主键

使用Flask-SQLALchemy管理数据库

在Flask-SQLALchemy中,数据库使用URL指定。

示例:配置数据库

from flask.ext.sqlalchemy import SQLALchemy

basedir=os.path.abspath(os.path.dirname(__file__)) 
#os.path.abspath()返回绝对地址,os.path.dirname(__file__)输出正在运行的脚本所在的完整路径

app=Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URL']=\'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
#配置对象中还有一个很有用的选项,即 SQLALCHEMY_COMMIT_ON_TEARDOWN 键,将其设为 True时,每次请求结束后都会自动提交数据库中的变动。

db=SQLALchemy(app)  #db 对象是 SQLAlchemy 类的实例,表示程序使用的数据库

定义模型

Flask-SQLAlchemy 创建的数据库实例为模型提供了一个基类以及一系列辅助类和辅助函数。

示例:定义Role和User模型

class Role(db.Model):
  __tablename__='roles'
  id=db.column(db.interger,primary_key=True)  #primary_key用来设置该列为主键
  name=db.column(db.String(64),unique=True)   #unique表示这列不能出现重复的数据
  #db.Column的一个参数用来设置该列的数据类型

  def __repr__(self):
    return '<User %r>' % self.username   # __repr()__ 方法,返回一个具有可读性的字符串表示模型,可在调试和测试时使用。

class User(db.Model):
  __tablename__='users'
  id=db.Column(db.Integer,primary_key=True)
  username=db.Column(db.String(64),unique=True,index=True)

  def __repr__(self):
    return '<User %r>' % self.username

关系

关系型数据库使用关系把不同表中的行联系起来

示例:关系

class Role(db.Model):
  #...
  users=db.relationship('User',backref='role')
 0.添加到Role模型中的users属性代表这个关系的面向对象视角。对于一个Role类的实例,其users属性将返回与角色相关联的用户组成的列表。
 1.db.Relationship()第一个参数表明这个关系的另一端是哪个模型(类)。如果模型类尚未定义,可使用字符串形式指定。
 2.db.Relationship()第二个参数backref,将向User类中添加一个role属性,从而定义反向关系。这一属性可替代role_id访问Role模型,此时获取的是模型对象,而不是外键的值。


class User(db.Model):
  #...
  role_id=db.Column(db.integer,db.ForeignKey('roles.id'))
#添加到 User 模型中的 role_id 列被定义为外键,就是这个外键建立起了关系。传给 db.ForeignKey() 的参数 'roles.id' 表明,这列的值是 roles 表中行的 id 值。

数据库操作

创建,插入,修改,删除,查询行

#创建
db.creat_all()  #如果你查看程序目录,会发现新建了一个名为 data.sqlite 的文件

#插入行
from hello import Role,User
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)
#这些新建对象的 id属性并没有明确设定,因为主键是由 Flask-SQLAlchemy 管理的。现在这些对象只存在于Python 中,还未写入数据库。因此 id 尚未赋值

#通过数据库会话(db.session)管理对数据库所做的改动,数据库会话也称为*事务*
db.session.add(admin_role)
db.session.add(mod_role)
db.session.add(user_role)
...
#或者简写成
db.session.add_all([admin_role,mod_role,user_role,user_john,user_susan,user_david])

#调用commit()方法提交会话,把对象写入数据库
db.session.commit()

#修改行
admin_role.name='Administrator'
db.session.add(admin_role)
db.session.commit()

#删除行
db.session.delete(mod_role)
db.session.commit()

#查询行
Role.query.all()
User.query.all()

#使用过滤器配置query对象进行进行更精确的查询
User.query.filter_by(role=user_role).all()

#动态关系
class Role(db.Model):
  #...
  users=db.realationship('User',backref='role',lazy='dynamic')

在视图函数中操作数据库

示例:把用户输入的名字写入数据库

@app.route('/',methods=['GET','POST'])
def index():
  form=NameForm()
  if form.validate_on_submit():
    user=User.query.fliter_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
  from.name.data=''
  return redirect(url_for('index'))
return render_template('index.html',form=form,name=session.get('name'),known=session.get('knwon',Flase))

为了避免每次启动shell会话都要导入数据库实例和模型,为shell命令添加一个上下文

from flask.ext.script import Shell

def make_shell_context():
  return dict(app=app,db=db,User=User.Role=Role)
manger.add_command('shell',Shell(make_context=make_shell_context))
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,829评论 1 331
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,603评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,846评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,600评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,780评论 3 272
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,695评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,136评论 2 293
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,862评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,453评论 0 229
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,942评论 2 233
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,347评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,790评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,293评论 3 221
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,839评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,448评论 0 181
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,564评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,623评论 2 249

推荐阅读更多精彩内容