多对一,一对多
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
# modules = db.relationship('Module',backref='project')
modules = db.relationship('Module', back_populates='module_project')
class Module(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
project_id = db.Column(db.Integer, db.ForeignKey("project.id"))
module_project = db.relationship('Project', back_populates='modules')
modules,module_project 字段与DB中的表是没有关系的,只是在orm对象间进行使用。
relationship参数解释
param1,指明与哪个模型类产生联系
modules 作用是通过modules这一个属性来查询到关联的表的属性 ex project.modules,可自行命名,方便使用即可。
backref 反向引用,当已经查到一个module的时候如何获取对应的project module.project
backref 的缺点在于可读性不够强。反向引用只需要在一方定义,只需要声明关系即可
back_populates 显式的说明两张表的关系,这种方法是显示对应的,多方与单方都需要进行配置,可以提高健壮性,如果定义错误既会报错
backref vs back_populates
back_populates 需要双向显式说明,backref 只需要指明一遍隐式说明即可
back_populates 更麻烦,backref更简单
back_populates 更具有可读性,能很快知道各个表之间的关系
一对一
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
# modules = db.relationship('Module',backref='project')
modules = db.relationship('Module', backref='module_project', uselist=False)
多对多
适用场景
1,关系表值存储2个关联表的id作为外键,没有其他信息
2,关系表不能祖籍为模型操作
# 多对多,中间表
xuanke = db.Table("xuanke", db.column('user_id', db.Integer, db.ForeignKey('user.id')),
db.ForeignKey('subject_id'), db.Integer, db.ForeignKey('subject.id'))
class Subject(db.Model):
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(20))
class User(db.Model):
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(20))
subjects = db.relationship("Subject",secondary=xuanke,
backref=db.backref('users',lazy='dynamic'))
relationship参数解释
1,第一个参数,与哪个模型类产生关系
2,secondary 参数就是关系表 db.Table 声明一个表,该表不能通过orm直接使用,不可单独对词表进行查询
只能根据多对多关系查询到目标数据。
- secondary 接收的参数为db.Table声明的中间表对象,
- lazy日后理解
自引用关系
flask上下文机制
如果出现 outside context error 则是出现了关于flask上下文环境的问题,即 request,g,app,之类的全局变量脱离请求环境是无法访问的。
RequestContext() 请求上下文
AppContext() 应用上下文
来看一张图片
上图锁展示的是flask发送请求的流程,以及内部处理逻辑。
当一个flask请求进来之后,存储在环境变量envior中,请求会调用flask中的最小原形中的app.call方法里面的wsgi_app()方法初始化一个RequestContext(environ)并进行判断是否已生成上下文,生成则执行 ctx.push()将这个上下文推入一个栈中。 ```python
1,最小原形里面的app 是一个函数, 而flask 是对象,对象被调用是执行call方法 2,app.call 里面的函数 wsgi_app() 3, wsgi_app原码 会通过环境变量数据实例化一个 RequestContext(environ) 并执行ctx.push() 将这个请求上下文推入一个栈中 4,request_ctx.push() 先判断一下是否有一个 appContext 没有的话推入一个 5,_request_ctx_stack.top 就是现在的请求对象 6,_app_ctx_stack.top 就是现在的app对象 7,_request_ctx_stack.top 就是current_app 8, _app_ctx_stack.top 就是request ```