关系模型的数据库也成为SQL数据库。文档数据库和键值对数据库合称NOSQL数据库
1SQL数据库
关系型数据库把数据存储在表中,表对应程序中的实体。
win系统下安装mysql-python驱动出错
在`https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysql-python`下载的驱动,安装出错,解决方法,改名。。:http://blog.csdn.net/csdnjava2017/article/details/78159346
Flask-SQLAlchemy:
1.ORM:Object Relationship Mapping(模型关系映射)
2.flask-sqlalchemy是一套ORM框架
3.优点:操作数据库跟操作对象是一样的,一个表抽象成一个类,一条数据抽象成该类的一个对象。不需要写sql语句,只用操作对象就行。
使用flask-sqlalchemy创建模型与表的映射:
用flask-sqlalchemy链接数据库,语法如下:
dialect+driver://username:password@host:port/database #dialect是数据库,要小写,比如mysql,sqlite。driver是python的驱动,mysql的默认驱动是mysqldb,记得要先装驱动!不然会提示找不到该模块。
在config.py中添加配置信息:
DEBUG = True DIALECT = 'mysql' DRIVER = 'mysqldb'#要先装好flask-mysqldb USERNAME = 'root' PASSWORD = '' HOST = '127.0.0.1' POST = '3306' DATABASE = 'demo' SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,POST,DATABASE)
然后在脚本中,添加配置文件并初始化数据库
from flask import Flask,url_for,redirect,render_template from flask_sqlalchemy import SQLAlchemy import config#导入模块 app = Flask(__name__) app.config.from_object(config)#配置文件 db = SQLAlchemy(app)#初始化数据库
测试:
db.create_all()#测试是否成功连接
创建表:
# article表: # create table article( # id int primary key autoincrement, # title varchar(100) not null, # content text not null, # ) class Article(db.Model):#Model是db下的一个属性 __tablename__='article'#表名,双下划线表示规定的字段 id = db.Column(db.Integer,primary_key=True,autoincrement=True) #属性要映射到表中的一个字段 title = db.Column(db.String(100),nullable=False)#char和varchar用string content = db.Column(db.Text,nullable=False)
- 模型需要继承自db.Model,然后映射到表中的属性,必须写成db.Column
- db.Integer代表整型
- db.String代表是字符串
- db.Text代表text
- primary_key:主键
- autoincrement:自增长
- nullable=False:不能为空
- 最后要调用db.create_all()建表
使用flask-sqlalchemy实现数据的增删改查:
增:
#增加: article1 = Article(title='aaa',content='bbb') db.session.add(article1)#数据的增删改都是通过这个sqlalchemy中的session操作的
#这里的session不是flask的session事务。
#之前的操作只是存在会话当中,还要提交才能到数据库 db.session.commit()
查询:
#查 #select * from article where Article.title='aaa'; result = Article.query.filter(Article.title == 'aaa')#从Article模型中查找title为'aaa'的 #query类是从db.Model继承的。这个result返回的是Query对象,Query对象是个list #result = Article.query.filter(Article.title == 'aaa')[1]返回第二个,但是没有数据会抛出异常 #通常用result = Article.query.filter(Article.title == 'aaa').first()取第一条数据,没有数据会返回none print(result)#返回的是SQL语句 # result = Article.query.filter(Article.title == 'aa').all() # 这个返回result的对象是个数组 print(result[0].title)
改:
#改: #1.查询数据 article1 = Article.query.filter(Article.title == 'aa').first() # 2修改数据 article1.title = 'new title' # 3提交事务 db.session.commit()
删除:
#删 #1.查询数据 article1 = Article.query.filter(Article.title == 'new title').first() #2.删除数据 db.session.delete(article1) #3.提交事务 db.session.commit()
Flask-SQLAlchemy外键及其关系:
backref反向引用,可以将一对多的关系转换成一对一。
1.外键:
#mysql语句: #create table users ( # id int primary key autoincrement, # username varchar(100) nut null #) class User(db.Model): __tablename__='user' id = db.Column(db.Integer,primary_key=True,autoincrement=True) username = db.Column(db.String(100),nullable=False) #mysql语句: #create table article ( # id int primary key autoincrement, # title varchar(100) not null, # contnet text not null, # author_id int, # foreign key 'author_id' references 'users.id' #) class Article(db.Model): __tablename__='article' id = db.Column(db.Integer,primary_key=True,autoincrement=True) title = db.Column(db.String(100),nullable=True) content = db.Column(db.Text,nullable=True) author_id = db.Column(db.Integer,db.ForeignKey('user.id')) author = db.relationship('User',backref=db.backref('articles')) #第一个参数是模型(Model)的名字 #articles是给反向引用的名字 #backref反向引用 #正向引用是Article访问作者,反向引用是通过User访问Article, # 在Article上建立了一个名为Article.author的User对象的合集 # 在User表中建立了一个articles属性,引用父对象Article article = Article(title='aaa',content='bbb') article.author = User.query.filter(User.id == 1).first() #上面这两句相当于 #article = Article(title='aaa',content='bbb',author_id=1) db.session.add(article) db.session.commit() article = Article.query.filter(Article.title == 'aaa').first() print(article.author.username)
- author = db.relationship('User',backref=db.backref('articles')):给Article添加了一个author属性,可以访问这篇文章的作者的数据,像访问普通模型一样。
- backref是定义反向引用,可以通过User.articles访问这个模型缩写的所有文章。
- 可以理解成:本来是一个用户对应多篇文章,现在转化为一篇文章对应一个用户。
Flask-Script
- Flask-Script的作用是可以通过命令行的形式操作Flask。例如通过命令跑一个服务器,设置数据库,定时任务等。
-
如果直接在manage.py中写命令,那么在终端就只需要python manage.py command_name就可以了
-
如果把一些命令集中在一个文件中,那么在终端就需要输入一个父命令,如`python manage.py db init`
- 例子:
-
#manage.py from flask_script import Manager from blog import app from db_scripts import DBManager manager = Manager(app) @manager.command def runserver(): print('服务器跑起来了') manager.add_command('db',DBManager) if __name__ == '__main__': manager.run() #在控制台输入 #python manager.py runserver
-
#db_script.py #数据库相关文件 from flask_script import Manager DBManager = Manager() @DBManager.command def init(): print('数据库初始化完成') @DBManager.command def migrate(): print('数据表迁移成功') #在控制台输入 #python manage.py db init #python manage.py db migrate
循环引用:
- 循环引用产生的原因:两个模块相互引用了。
- 如何解决:加入第三个模块,切断循环引用的线条
- db.init_app(app)方法就是用来处理循环引用的,可以初始化sqlalchemy
db.create_all()报错:No application found. Either work inside a view function or push an application context
解决:用户访问服务器时,会将app放入服务器中的app栈,如果没有用户访问(没有执行视图函数)服务器中的app栈为空,那么初始化app时就会报错,所以要手动将app推到服务器中的app栈中。
with app.app_context():
db.create_all()
https://stackoverflow.com/questions/19437883/when-scattering-flask-models-runtimeerror-application-not-registered-on-db-w
flask-migrate
- 采用db.create_all在后期修改字段的时候,要先删除表,才能用db.create_all建表,会影响之前存的数据。flask-migrate可以在每次修改模型后,将修改的东西映射到数据库中。
- 使用flask_migrate必须借助flask_scripts。
- MigrateCommand中包含了所有和数据库相关的命令。
- 相关命令:
-
- `python manage.py db init`:初始化一个迁移脚本的环境,只需要执行一次
- `python manage.py db migrate`:将模型生成迁移文件,只要模型更改了,就需要执行一遍这个命令。
- `python manage.py db upgrade`:将迁移文件真正的映射到数据库中。每次运行了migrate命令后,就记得要运行这个命令。
-
需要将想要映射到数据库中的模型,都要导入到manage.py文件中,不然不会映射到数据库中。
from flask_script import Manager from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate,MigrateCommand from models import Article from models import User db = SQLAlchemy(app) manager = Manager(app) #1要使用flask_migrate,必须绑定app和db migrate = Migrate(app,db) #2.把MigrateCommand命令添加到manager中 manager.add_command('db',MigrateCommand)