一,配置

1,SQLALchemy的配置单独使用config.py文件
2,满足如下要求:
#dialect+driver://username:password@host:port/database

具体说明如下:

# dialect:是数据库的实现,比如MySql,SQLlite,且转换为小写
# driver:对应的驱动,比如MySql的驱动是MySqldb
# username:连接数据库的用户名
# password:密码
# host:连接数据库的域名
# port:数据库监听的端口号
# database:是连接的数据库的名字,创建数据库语句为:
SQL语句:"""create database db_demo1(database_name) charset utf8""" # 如果以上输出了1则说明SQLAlchemy能成功连接到数据库。 DIALECT = "mysql"
DRIVER = "mysqldb"
USERNAME = "root"
PASSWORD = ''
HOST = "127.0.0.1"
PORT = ""
DATABASE = "db_demo3" SQLALCHEMY_DATABASE_URI="{}+{}://{}:{}@{}:{}/{}".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)
"""指定一个名为SQLALCHEMY_DATABASE_URI的固定变量,注意是固定的写法"""
SQLALCHEMY_TRACK_MODIFICATIONS =False

3,在主程序中引用并配置:

#引用
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config #配置
app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app)

二,具体使用

1,数据库创建与删除

2,表的创建

class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
username = db.Column(db.String(),nullable=False) class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
title = db.Column(db.String(),nullable=False)
content = db.Column(db.Text,nullable=False) author_id = db.Column(db.Integer,db.ForeignKey('user.id')) #后面跟表名
db.create_all() #创建后一定记得这一步

创建后用Navicat查看为:

创建两个空表后需要写入数据:

    # user1 = User(username="zy")
# db.session.add(user1)
# db.session.commit()
#
# user2 = User(username="ly")
# db.session.add(user2)
# db.session.commit()
#
# article1 = Article(title="zy1", content="zy1",author_id=)
# article2 = Article(title="zy2", content="zy2", author_id=)
# article3 = Article(title="ly1", content="ly1", author_id=)
# article4 = Article(title="ly2", content="ly2", author_id=)
# db.session.add(article1)
# db.session.add(article2)
# db.session.add(article3)
# db.session.add(article4)
# db.session.commit()

User模块下user表的结构应该是:

id username
1 zy
2 ly

Article模块下articler表的结构应该是:

id title content author_id
1 zy1 zy1 1
2 zy2 zy2 1
3 ly1 ly1 2
4 ly2 ly2 2

3,增删改查(这里代码没怎么修改,主要看黄字部分)

def hello_world():
# 数据的增加:
# article1 = Article(title="a",content="A")
# db.session.add(article1)
# # 数据的增删改查都是在“session”里做的,但是它和web中的“session”不一样。
# db.session.commit() #每一步的提交都不能忘记 # 数据的查:
# # select * from article where title = "aaa";
# result = Article.query.filter(Article.title == "a")[]
# print(result.title,result.content)
# # query来源于db.Model,查找都是基于query的。 # 数据的改:
# # ,先把你要更改的数据查找出来
# article1 = Article.query.filter(Article.title == "a").first()
# # ,吧这条数据,你需要的地方进行修改
# article1.title = "new title"
# # ,做事务的提交
# db.session.commit() #数据的删:
# ,把需要删除的数据查找出来
article1 = Article.query.filter(Article.title == "a").first()
# ,把这条数据删除
db.session.delete(article1)
# ,做事务的提交
db.session.commit() return 'Hello World!'

4,外键约束

对于以下两个需求来讲,实现如下,这是属于常规的且不方便的做法:

# 方案一:
# # 找到标题为“zy1”的文章的作者
# result1 = Article.query.filter(Article.title == "zy1").first()
# result2 = User.query.filter(User.id == result1.author_id).first()
# print(result2.username)
#
# # 找到zy用户写过的所有文章
# result3 = User.query.filter(User.username == "zy").first()
# result4 = Article.query.filter(Article.author_id == result3.id).all() #all
# for i in result4:
# print(i.title)

可以看到二.2部分只有一个单纯的外键关系(“author_id = db.Column(db.Integer,db.ForeignKey('user.id')) #后面跟表名”),对于上述两个操作不太方便,那么我们如何让上述操作更简单呢?

就在原源代码上加入黄代码那句:

class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
username = db.Column(db.String(),nullable=False) class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
title = db.Column(db.String(),nullable=False)
content = db.Column(db.Text,nullable=False) author_id = db.Column(db.Integer,db.ForeignKey('user.id')) #跟表名 author = db.relationship('User', backref=db.backref('articles')) #后面跟模块名
  # 给“Article”这个模型添加一个“author”属性,可以访问这篇文章的作者的数据,像普通访问一样。
  # “backref”是定义反向引用,是通过“User.articles”这个模型访问这个模型的所有文章。
db.create_all()

注意加入的黄代码会改变表结构,这时候需要重建表,即drop操作和create就行。

对于之前两个操作而言可以有如下简便且实用操作,下面代码黄色部分重点关注:

# 方案二
# 找到标题为“zy1”的文章的作者(与下面的一段反向对应。)。
# article = Article.query.filter(Article.title == "zy1").first()
# print(article.author.username) # 找到zy用户写过的所有文章
user = User.query.filter(User.username == "zy").first()
result = user.articles #这里的result是返回的所有文章,所以是个list类型,这就是backref带来的反向引用的作用
print("{}的文章:".format(user.username))
for i in result:
print(i,"Title:",i.title,"Content:",i.content)

相当于在Article模块中从A表变为B表:

  • A表:
id
title
content
author_id
 
  • B表:

是是

id
title
content
author_id
author (=db.relationship('User', backref=db.backref('articles'))  #后面跟模块名)

===============================================================================

补充说明:

在一对多关系中,一个作者可以有多个文章。如图:

代码如下:

class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
title = db.Column(db.String(100),index=True)
body = db.Column(db.Text) class Author(db.Model):
__tablename__ = "author"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(100),unique=True)
phone = db.Column(db.String(11)) db.create_all()

那么我们需要分以下两个方面创建这种关系。

1,定义外键

因为外键只能存储
单一数据(标量),所以外键总是在“多”这一侧定义, 多篇文章属于同一个作者, 所以我们需要为每篇文章添加外键存储作者的主键值以指向对应的作者。

分析过程:为什么定义在“多”这一侧?如果在作者里定义一个外键article_id,则表示这个作者只能有一篇文章;如果在文章里定义一个外键author_id,则表示这个文章只能有一个作者。

故在Article模型中, 我们定义一个author_id字段作为外键:

class Article(db.Model):
...
author_id = db.Column(db.Integer, db.ForeignKey('author.id'))

2,定义关系属性

关系属性在一对多关系的“一”这一侧。 一个作者拥有多篇文章,在Author模型中, 我们定义了一个articles属性来表示对应的多篇文章:

class Author(db.Model):
...
articles = db.relationship('Article')

这个代码可以利用反向引用backref来写成:

class Article(db.Model):
...
author = db.relationship('Author', backref=db.backref('articles'))

 关于backref的用法可以为自动在另一侧简历关系属性:

最终代码:

class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
title = db.Column(db.String(100),index=True)
body = db.Column(db.Text)
author_id = db.Column(db.Integer,db.ForeignKey('author.id'))
author = db.relationship('Author', backref=db.backref('articles')) #1号代码,与2之间只能存在一个。 class Author(db.Model):
__tablename__ = "author"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(100),unique=True)
phone = db.Column(db.String(11))
articles = db.relationship('Article') #2号代码,与1之间只能存在一个。 db.create_all()

 另外注意两点:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app) class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
title = db.Column(db.String(100),index=True)
body = db.Column(db.Text)
author_id = db.Column(db.Integer,db.ForeignKey('author.id'))
author = db.relationship('Author', backref=db.backref('articles')) #1号代码,与2之间只能存在一个。 class Author(db.Model):
__tablename__ = "author"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(100),unique=True)
phone = db.Column(db.String(11))
# articles = db.relationship('Article') #2号代码,与1之间只能存在一个。 db.create_all() @app.route('/')
def hello_world():
foo = Author(name="Foo")
db.session.add(foo)
db.session.commit()
spam = Article(title="Spam")
ham = Article(title="Ham")
db.session.add(spam)
db.session.add(ham)
db.session.commit() spam.author_id = 1
db.session.commit() foo.articles.append(ham) #注意一:append
db.session.commit() foo.articles.remove(spam) #注意一:remove
db.session.commit() author1 = Author.query.filter(Author.name == "Foo").first()
result = author1.articles #注意二:这里的result是返回的所有文章,所以是个list类型
for i in result:
print("Foo的文章:",i,"Title:",i.title) return 'Hello World!' if __name__ == '__main__':
app.run()

=============================================================================

另外多对一,多对多的关系下次加

03SQLALchemy外键约束的更多相关文章

  1. mysql 外键约束备注

    梳理mysql外键约束的知识点. 1.mysql外键约束只对InnoDb引擎有效: 2.创建外键约束如下: DROP TABLE IF EXISTS t_demo_product; CREATE TA ...

  2. 如果你发现mysql的外键约束不管用了

    不知为何我机子上的mysql竟然默认关闭外键约束,导致我试了好多遍都可以插入非法值,以下语句可以开启约束 SET foreign_key_checks = 1; (0则关闭) 备忘

  3. Constraint6:更新外键约束(Foreign Key Constraint)的引用列

    在SQL Server中,表之间存在引用关系,引用关系通过创建外键约束(Foreign Key Constraint)实现.如果一个Table中的column被其他Table引用,那么该表是参考表,或 ...

  4. MySql 外键约束 之CASCADE、SET NULL、RESTRICT、NO ACTION分析和作用

    MySQL有两种常用的引擎类型:MyISAM和InnoDB.目前只有InnoDB引擎类型支持外键约束.InnoDB中外键约束定义的语法如下: ALTER TABLE tbl_name ADD [CON ...

  5. SQL Server 临时禁用和启用所有外键约束(高版本向低版本迁移数据)

    --获得禁用所有外键约束的语句 select 'ALTER TABLE [' + b.name + '] NOCHECK CONSTRAINT ' + a.name +';' as 禁用约束 from ...

  6. SqlServer禁用启用触发器、外键约束

    --禁用指定名称触发器 ALTER TABLE tbname DISABLE TRIGGER trigname --恢复指定名称触发器 ALTER TABLE tbname ENABLE TRIGGE ...

  7. sql查询指定表外键约束

    //////////////////查询指定表外键约束select a.name as 约束名, object_name(b.parent_object_id) as 外键表, d.name as 外 ...

  8. 转:使用DBUnit测试时违反外键约束的解决办法

    DBUnit是一个基于junit扩展的数据库测试框架.它提供了大量的类对与数据库相关的操作进行了抽象和封装.它会把数据库表里的数据和一个xml文件关联起来,也就是说它可以让数据在XML文件和数据库之间 ...

  9. mysql启动和关闭外键约束的方法(FOREIGN_KEY_CHECKS)

    在MySQL中删除一张表或一条数据的时候,出现 [Err] 1451 -Cannot delete or update a parent row: a foreign key constraint f ...

随机推荐

  1. Python——一个简单的类的创建和应用

    1.创建类,设置属性和给属性设定默认值,设置方法并访问类的属性: 2.利用类创建多个实例,以及调用类的方法的两种办法: 3.设置更新属性的函数,并更新实例的属性. class dog(object): ...

  2. docker常用命令总结

    1.docker ps  查看当前正在运行的容器 2.docker ps -a 查看所有容器的状态 3.docker start/stop id/name     启动/停止某个容器 4.docker ...

  3. 关于NPOI导入的时候有时出现乱码解决办法

    手上这个项目之前客户说过导入的时候回出现乱码问题,一直没用重视,现在自己做做一个功能,乱码经常出现,开始以为是代码的问题,最后百度了试了很多方法猜找到解决办法: 乱码页面如下: 解决办法: 打开IIS ...

  4. 出现: object() takes no parameters 之后应该如何修改

    这个错误花费了很多的时间去解决,包括重写代码也无济于事. 因为粗心,浪费了很多的时间在这个上面,特写此博客来记录,也希望朋友们不要粗心,特别是初学者. 接下来进入正文: 当在写self.XXX  下方 ...

  5. elasticsearch 踩坑

    1.elasticsearch head安装 集群连不上,修改配置 add http.cors.enabled: true you must also set http.cors.allow-orig ...

  6. JS判断数组的值出现的次数,以及去重

    var arr = ["曹阳","曹阳","曹阳","张三","张三","张三" ...

  7. Python规范

    1.命名 Django文件命名 小写+下划线 类:驼峰 2.edit 执行环境 work direction 到当前项目目录 3.类要加注释 4.去数据库找数据时需要try捕获异常,防止数据库连接断掉 ...

  8. Linux下定时备份文件

    一. 编写脚本 编写一个脚本文件,使脚本可以执行备份命令. 例如,将文件目录 /home/backups/balalala 备份到/home目录下,并压缩. 1. 创建脚本 命令格式: touch 路 ...

  9. git 命令笔记

    切换 git 远程仓库HEAD分支 $ git remote set-head origin some_branch

  10. ESP8266莫名重启或者死机问题

    多半是内存使用不当 1. 如果你要用很大长度的数组,那么可以换用更小的数据类型.比如,int值要占用两个字节,你可以用byte(只占用一个字节)代替:    2. esp8266有时会莫明重启,大部分 ...