03SQLALchemy外键约束
一,配置
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外键约束的更多相关文章
- mysql 外键约束备注
梳理mysql外键约束的知识点. 1.mysql外键约束只对InnoDb引擎有效: 2.创建外键约束如下: DROP TABLE IF EXISTS t_demo_product; CREATE TA ...
- 如果你发现mysql的外键约束不管用了
不知为何我机子上的mysql竟然默认关闭外键约束,导致我试了好多遍都可以插入非法值,以下语句可以开启约束 SET foreign_key_checks = 1; (0则关闭) 备忘
- Constraint6:更新外键约束(Foreign Key Constraint)的引用列
在SQL Server中,表之间存在引用关系,引用关系通过创建外键约束(Foreign Key Constraint)实现.如果一个Table中的column被其他Table引用,那么该表是参考表,或 ...
- MySql 外键约束 之CASCADE、SET NULL、RESTRICT、NO ACTION分析和作用
MySQL有两种常用的引擎类型:MyISAM和InnoDB.目前只有InnoDB引擎类型支持外键约束.InnoDB中外键约束定义的语法如下: ALTER TABLE tbl_name ADD [CON ...
- SQL Server 临时禁用和启用所有外键约束(高版本向低版本迁移数据)
--获得禁用所有外键约束的语句 select 'ALTER TABLE [' + b.name + '] NOCHECK CONSTRAINT ' + a.name +';' as 禁用约束 from ...
- SqlServer禁用启用触发器、外键约束
--禁用指定名称触发器 ALTER TABLE tbname DISABLE TRIGGER trigname --恢复指定名称触发器 ALTER TABLE tbname ENABLE TRIGGE ...
- sql查询指定表外键约束
//////////////////查询指定表外键约束select a.name as 约束名, object_name(b.parent_object_id) as 外键表, d.name as 外 ...
- 转:使用DBUnit测试时违反外键约束的解决办法
DBUnit是一个基于junit扩展的数据库测试框架.它提供了大量的类对与数据库相关的操作进行了抽象和封装.它会把数据库表里的数据和一个xml文件关联起来,也就是说它可以让数据在XML文件和数据库之间 ...
- mysql启动和关闭外键约束的方法(FOREIGN_KEY_CHECKS)
在MySQL中删除一张表或一条数据的时候,出现 [Err] 1451 -Cannot delete or update a parent row: a foreign key constraint f ...
随机推荐
- 关于js dtGrid报错长度的问题
错误js截图 Uncaught TypeError: Cannot read property 'length' of undefined 翻译:Uncaught TypeError:无法读取未定义的 ...
- Swift PlayGround无限Running问题
这个问题我想肯定很多人都有遇到过,如果你正好面试iOS,用这个playground写算法的话遇到这种情况只能hehe了-- 我是这样解决的,一开始我build project的时候选得是iOS的pla ...
- WordPress plugin Contact Form [CSRF → LFI] vulnerable 2019-03-17
# Exploit Title: Contact Form by WD [CSRF → LFI]# Date: 2019-03-17# Exploit Author: Panagiotis Vagen ...
- 通过DeviceIoControl读磁盘的方式读取独占文件内容
前言 windows操作系统中常见的一个文件存储系统是NTFS.在这个文件系统中MFT是它的核心. 图一 MFT是一个数据结构,上图是它的结构,它主要用来存放每个文件和目录在磁 ...
- 417 事件、监听、jQuery、轮播手动
am:通用事件 a链接事件阻止默认行为 return false HTML元素大都包含了自己的默认行为,例如:超链接.提交按钮等.我们可以通过在绑定事件中加上return false来阻止它的默认行为 ...
- P5301 [GXOI/GZOI2019]宝牌一大堆
题目地址:P5301 [GXOI/GZOI2019]宝牌一大堆 这里是官方题解(by lydrainbowcat) 部分分 直接搜索可以得到暴力分,因为所有和牌方案一共只有一千万左右,稍微优化一下数据 ...
- appniu踩坑
1.pyCharm识别不到appnium-python-client 解决:新建项目注意选择环境,查看Project Interpreter中是否识别到了appnium-python-client 还 ...
- 微信中音乐播放在ios不能自动播放解决
在微信中,ios手机下面音乐被自动禁掉无法自动播放,我们可以执行触发body上的元素,自动进行播放. //音乐 var x = document.getElementById("myAudi ...
- 前端笔记知识点整合之JavaScript(四)关于函数、作用域、闭包那点事
一.自定义函数function 函数就是功能.方法的封装.函数能够帮我们封装一段程序代码,这一段代码会具备某一项功能,函数在执行时,封装的这一段代码都会执行一次,实现某种功能.而且,函数可以多次调用. ...
- expect 批量自动部署ssh 免密登陆
[root@node2 ssh]# cat auto_ssh.sh #!/usr/bin/expect -f ########################################## #通 ...