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 = '1234'
HOST = "127.0.0.1"
PORT = "3306"
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__)
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(100),nullable=False)
class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
title = db.Column(db.String(100),nullable=False)
content = db.Column(db.Text,nullable=False)
author_id = db.Column(db.Integer,db.ForeignKey('user.id')) #后⾯跟表名
sql约束条件大于0创建后⽤Navicat查看为:
创建两个空表后需要写⼊数据:
# user1 = User(username="zy")
# db.session.add(user1)
# db.sessionmit()
#
# user2 = User(username="ly")
# db.session.add(user2)
# db.sessionmit()
#
# article1 = Article(title="zy1", content="zy1",author_id=1)
# article2 = Article(title="zy2", content="zy2", author_id=1)
# article3 = Article(title="ly1", content="ly1", author_id=2)
# article4 = Article(title="ly2", content="ly2", author_id=2)
# db.session.add(article1)
# db.session.add(article2)
# db.session.add(article3)
# db.session.add(article4)
# db.sessionmit()
User模块下user表的结构应该是:
id username
1zy
2ly
Article模块下articler表的结构应该是:
id title content author_id
1zy1zy11
2zy2zy21
3ly1ly12
4ly2ly22
3,增删改查(这⾥代码没怎么修改,主要看黄字部分)
def hello_world():
# 数据的增加:
# article1 = Article(title="a",content="A")
# db.session.add(article1)
# # 数据的增删改查都是在“session”⾥做的,但是它和web中的“session”不⼀样。
# db.sessionmit()  #每⼀步的提交都不能忘记
# 数据的查:
# # select * from article where title = "aaa";
# result = Article.query.filter(Article.title == "a")[0]
# print(result.t)
# # query来源于db.Model,查都是基于query的。
# 数据的改:
# # 1,先把你要更改的数据查出来
# article1 = Article.query.filter(Article.title == "a").first()
# # 2,吧这条数据,你需要的地⽅进⾏修改
# article1.title = "new title"
# # 3,做事务的提交
# db.sessionmit()
#数据的删:
# 1,把需要删除的数据查出来
article1 = Article.query.filter(Article.title == "a").first()
# 2,把这条数据删除
db.session.delete(article1)
# 3,做事务的提交
db.sessionmit()
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(100),nullable=False)
class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
title = db.Column(db.String(100),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”这个模型访问这个模型的所有⽂章。
注意加⼊的黄代码会改变表结构,这时候需要重建表,即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))
那么我们需要分以下两个⽅⾯创建这种关系。
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之间只能存在⼀个。
 另外注意两点:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config
app = Flask(__name__)
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之间只能存在⼀个。
@ute('/')
def hello_world():
foo = Author(name="Foo")
db.session.add(foo)
db.sessionmit()
spam = Article(title="Spam")
ham = Article(title="Ham")
db.session.add(spam)
db.session.add(ham)
db.sessionmit()

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。