网站建站大约多少钱,网站手机端做app开发,程序员需要考什么证书,深圳搭建p2p网站文章目录 5 数据库5.1 数据库的分类5.2 ORM5.3 使用Flask_SQLAlchemy5.4 数据库操作5.5 定义关系5.6 更新数据库表5.7 数据库进阶小结 5 数据库
这一章学习如何在Python中使用DBMS#xff08;数据库管理系统#xff09;#xff0c;来对数据库进行管理和操作。本书使用SQLit… 文章目录 5 数据库5.1 数据库的分类5.2 ORM5.3 使用Flask_SQLAlchemy5.4 数据库操作5.5 定义关系5.6 更新数据库表5.7 数据库进阶小结 5 数据库
这一章学习如何在Python中使用DBMS数据库管理系统来对数据库进行管理和操作。本书使用SQLite作为示例。 注按下CtrlF5或ShiftF5可以清除浏览器缓存。 5.1 数据库的分类
分为SQLStructured Query Language数据库和NoSQLNot Only SQL数据库。
SQL稍显复杂但不容易出错可以适应大部分场景。NoSQL灵活效率高可扩展性好等。 1、文档存储使用类json格式来表示数据2、键值对存储通过键来存取数据读写很快常作为缓存使用。
5.2 ORM ORMObject-Relational Mapping对象关系映射。 作用
处理查询参数的转义防止注入。为不同的DBMS提供统一的接口。能直接使用Python操作数据库不需要写SQL语句。
ORM实现了三层映射关系表 -- Python类字段 -- 类属性记录 -- 类实例。
# 定义表
from foo_orm import Model, Column, String
class Contact(Model):__tablename__ contactsname Column(String(100), nullableFalse)# 插入记录
contact Contact(namezhang san)5.3 使用Flask_SQLAlchemy
1、连接数据库
首先连接数据库需要指定URIUniform Resource Identifier统一资源标识符URL统一资源定位符是它的子集。 常用的数据库URI格式p143 SQLite是基于文件的DBMS不需要数据库服务器只需要指定数据库文件的绝对路径。配置数据库URI的代码如下
from flask import Flask
import os
from flask_sqlalchemy import SQLAlchemyapp Flask(__name__)
t app.config[SQLALCHEMY_DATABASE_URI] os.getenv(DATABASE_URL, sqlite:/// os.path.join(app.root_path, data.db))
db SQLAlchemy(app)print(t)
print(db)运行输出
sqlite:///D:\code_all\gitCode\helloflask_learn\数据库\data.db
SQLAlchemy补充os.getenv是一个Python标准库函数它用于从环境变量中获取指定的值。这个函数的第一个参数是要查找的环境变量名称第二个参数是默认值如果未找到指定的环境变量则返回这个默认值。 2、定义数据库模型
模型类继承自SQLAlchemy提供的db.Model基类表的字段由db.Column类的实例表示。 SQLAlchemy常用的字段类型p144 常用的字段参数p145 class Note(db.Model):id db.Column(db.Integer, primary_keyTrue)body db.Column(db.Text)表名称会根据模型的类名称自动生成可用__tablename__属性指定。 字段名默认为类属性名看用name关键字参数指定。
3、创建数据库和表
db.create_all()可以查看模型对象的建表SQL语句
from app import Note
from sqlalchemy.schema import CreateTable
print(CreateTable(Note.__table__))改动模型类后再次调用create_all()不会更新表结构。可以调用drop_all()方法删除数据库和表然后重建。
可以自定义一个flaks命令完成数据库的创建工作对于sqlite创建成功后会生成一个数据库文件如data.db。
import click
app.cli.command()
def initdb():db.create_all()click.echo(Initialized database)5.4 数据库操作
SQLAlchemy使用数据库会话也称为事务来管理数据库操作会话代表一个临时存储区对会话对象调用commit()方法时改动才被提交到数据库。调用rollback()方法可以撤销会话中未提交的改动。
1、CRUD
即Create、Read、Update、Delete。
Create
note Note(bodyhello, world)
db.session.add(note)
db.session.commit()通过add_all()可以一次提交一个列表。
Read
模型类.query.过滤方法.查询方法
Note.query.filter(Note.bodyhello, world).firstQuery对象调用过滤方法的返回值仍然是一个Query对象就像SQL的操作对象和返回结果都是表。查询方法返回的是模型类实例。 常用的SQLAchemy查询方法p148 all()first() count() paginate()get(ident)等 常用过滤方法p150 filter()filter_by()order_by()limit()group_by()等 常用查询操作符p150 LIKEINNOT INANDOR等。 Update
note Note.query.get(2)
note.body hello, flask
db.session.commit()Delete
note Note.query.get(2)
db.session.delete(note)
db.session.commit()2、在视图函数里操作数据库
与在python shell中基本一致。
5.5 定义关系
1、配置Python Shell上下文
使用app.shell_context_processor装饰器注册一个shell上下文处理函数返回包含变量和变量值的字典。
app.shell_context_processor
def make_shell_context():return dict(dbdb, NoteNote)2、一对多关系
定义一对多关系包含两个部分定义外键和定义关系属性。其中关系属性相当于一个快捷查询不会作为字段被写入到数据库中。下面的关系属性articles会返回该作者所有文章的记录列表。
class Author(db.Model):...articles db.relationship(Article)class Article(db.Model):...author_id db.Column(db.Integer, db.ForeignKey(athor.id))可以在两侧都定义一个关系属性称为双向关系需要用到back_populates关键字参数值为另一侧的关系属性名。
class Author(db.Model):...articles db.relationship(Article, back_populatesauthor)class Article(db.Model):...author_id db.Column(db.Integer, db.ForeignKey(athor.id))author db.relationship(Author, back_populatesarticles)可以使用backref简化关系定义p163 疑惑为什么要手动在两侧都指定反向引用而不是添加了外键属性之后就自动的呢是采用了数据库中的索引吗 定义关系后建立关系有两种方式一种是为外键字段赋值另一种是通过操作关系属性。
# 为外键字段赋值
article_A.author_id 1
# 操作关系属性: append, remove, pop
Mike.articles.append(article_A)常用关系函数参数p161 常用关系记录加载方式p161 3、一对一关系
实际上是在通过建立一对多关系的双向关系的基础上转化而来只是在原来”一“的一方设置userlistFalse将集合属性变为标量属性。此后无法再使用列表语义操作如append方法。
class Contry(db.Model):...capital db.relationship(Capital, uselistFalse)
class Capital(db.Model):...contry_id db.Column(db.Integer, db.ForeignKey(country.id))contry db.relationship(Country)4、多对多关系
一对多关系中在“多”的一方存放外键则“多”一方的每条记录只能有一条关系。我们可以单独创建一个关联表(db.Table)来存储外键表示多对多关系。使用secondary参数来指定关联表。
association_table db.Table(association,db.Column(student_id, db.Integer, db.ForeignKey(student.id)),db.Column(teacher_id, db.Integer, db.ForeignKey(teacher.id)))class Student(db.Model):...teachers db.relationship(Teacher, secondaryassociation_table, back_populatesstudents)class Teacher(db.Model):...students db.relationship(Student, secondaryassociation_table, back_populatesteachers) 5.6 更新数据库表
1、重新生成表
方法很简单但缺点是会丢失原来的所有数据。
db.drop_all()
db.create_all()2、使用Flask-Migrate迁移p169
可以保留数据库中原有的数据。自动生成的迁移命令不一定可靠必要时检查一下。
flask db init # 创建迁移环境
flask db migrate # 生成迁移脚本
flask db upgrade # 应用迁移
flask db downgrade # 撤销一次迁移5.7 数据库进阶
1、级联操作p172
在relationship方法可以配置cascade参数所有可用值为save-updatemergerefresh-expireexpungedelete。默认值为save-updatemerge。
class Post(db.Model):...comments db.relationship(..., cascadesave-update, merge, delete)save-updatedb.session.add()将Post对象添加到数据库会话时相关的Comment对象也会被添加到数据库会话。 deletePost记录被删除时相关的Comment记录也会被删除。 delete-orphanPost与Comment记录解除关系操作时相应的Comment记录会被删除。 all包含除了delete-orphan之外的所有可用值。
2、事件监听p176
在Flask中有请求回调函数而SQLAlchemy也提供了listens_for()装饰器来注册事件回调函数。装饰器接受两个参数target表示监听的对象identifier表示被监听事件的类型。被注册的监听函数需要接收对应事件方法的所有参数。 疑惑“事件方法”指什么怎么知道它有哪些参数 class Draft(db.Model):...edit_time ...db.event.listens_for(Draft.body, set, namedTrue)
def increment_edit_time(**kwargs):if kwargs[target].edit_time is not None:kwargs[target].edit_time 1设置named参数为True可以使用kwargs接收所有参数不知道为啥。kwargs中的target参数表示触发事件的模型类实例。 小结 SQLAlchemy入门教程p177http://docs.sqlalchemy.org/en/latest/orm/tutorial.html 数据库这一章我看得有点拖拉正值开学可能需要好些天才能找回学习状态。大部分东西我还是之前都有所了解因此看得比较流畅。在最近开发自己的玩具程序的过程中数据库这一环节可给我制造了不少麻烦特别是配环境它在我眼里的黑盒程度又比较高书中说到本章只是一个简单的介绍不过暂时于我也够用了。