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 ...
随机推荐
- C#中Dictionary的介绍
关键字:C# Dictionary 字典 作者:txw1958原文:http://www.cnblogs.com/txw1958/archive/2012/11/07/csharp-dictionar ...
- Python自动化中的键盘事件
1) from selenium import webdriver 加载模块 2) b = webdriver.Friefox() 打开浏览器 3) b.get(‘http://xxxxxxx’) 打 ...
- 一个账户接管几乎所有阿里巴巴网站(CSRF漏洞+WAF绕过)
场景 文章是关于某些客户端漏洞导致几个阿里巴巴网站的帐户被接管. 条件 TL;DR 必要条件,例如JSONP,某些浏览器处理cookie等行为. 攻击原理 大多数阿里巴巴的网站加载并执行外部JavaS ...
- selenium中webdriver识别class属性多个值中有空格的解决方案
初学自动化测试,貌似大家十有八九都是用百度网站进行练手的,特此感谢百度. http://www.baidu.com 页面中主要就是搜索框和提交按钮: 输入框各元素属性:<input id=&qu ...
- cadence学习一------>介绍
Allegro常用组件: 1.orcad capture cis------>>原理图 2.PCB editor----->>PCB 3.PAD designer------- ...
- Mybatis 常用注解
Mybatis常用注解对应的目标和标签如表所示: 注解 目标 对应的XML标签 @CacheNamespace 类 <cache> @CacheNamespaceRef 类 <cac ...
- 帆软报表(finereport)间格运算常用公式
1.1在C3(占比)单元格中直接使用占比公式:=PROPORTION(B3):占比:当前值占总值的比例 1.2 计组内占比注:C2[!0]{A2=$A2},表示C2扩展出来地区相同的单元格.sum(C ...
- mybatis:SQL拦截器
打印执行的SQL语句 import java.sql.Connection; import java.text.DateFormat; import java.util.Date; import ja ...
- web开发-前后端分离原理
前言 前后端分离已成为互联网项目开发的业界标准使用方式,通过Nginx+Tomcat的方式(也可以中间加一个Node.js)有效的进行解耦,并且前后端分离会为以后的大型分布式架构.弹性计算架构.微服务 ...
- vs/windows程序找不到入口点cuvidGetDecodeStatus于AppDecGL.exe动态链接库上
解决方法:这个问题的原因是由于使用的英伟达显卡驱动版本不够新,更新显卡驱动即可. 找了一个多月的原因,终于知道起源了.最终问题还是出在了nvcuvid.lib/.dll上面.通过分析vs调试信息可以得 ...