如何将 APScheduler JobStore 与 SQLAlchemy 模型(外键)相关联 - Python Flask
How to relate APScheduler JobStore with SQLAlchemy Models (foreign key) - Python Flask
我有一个 Python Flask 应用程序,使用 flask.ext.sqlalchemy
和 apscheduler.schedulers.background
。我已经创建了一个 JobStore 并获得了一个名为 apscheduler_jobs
的 table 具有以下字段:
|id |next_run_time|job_state|
------------------------------
|TEXT| REAL | TEXT |
我想将一个 SQLAlchemy 模型对象与 table 相关联,使用如下方式:
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
scheduler.add_jobstore('sqlalchemy', url=app.config['SQLALCHEMY_DATABASE_URI'])
class Event(db.Model):
__tablename__ = "event"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
jobs = db.relationship('scheduler', backref='apscheduler_jobs')
所以我想使用 APScheduler apscheduler_jobs 中的 table,然后将其与我的 Event 对象的外键相关联。最后一行基本上会中断,因为 "scheduler" 不是定义的 SQLAlchmey 模型
qlalchemy.exc.InvalidRequestError: When initializing mapper Mapper|Event|event, expression 'scheduler' failed to locate a name ("name 'scheduler' is not defined"). If this is a class name, consider adding this relationship() to the <class 'project.models.Event'> class after both dependent classes have been defined.
所以我认为我需要一个中间模型 class 称为 "job" 或其他东西,然后将其与 apscheduler_jobs 相关联,但这里的某些东西仍然感觉很糟糕 - 因为 APScheduler 正在制作这个 table up 我无法控制那里发生的事情 - 我应该担心吗?
编辑 1:
所以我创建了 2 个模型,一个 "Event" 然后一个 "Job","Job" 然后与 table apscheduler_jobs
相关
class Job(db.Model):
__tablename__ = "job"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
apscheduler_job_id = db.Column(db.Integer, db.ForeignKey('apscheduler_jobs.id'))
event_id = db.Column(db.Integer, db.ForeignKey('event.id'))
问题是当我删除数据库并重新创建它时抛出错误:
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'job.apscheduler_job_id' could not find table 'apscheduler_jobs' with which to generate a foreign key to target column 'id'
现在我可以在我的数据库创建脚本中解决这个问题,但我还是觉得我做错了方法
EDIT2
我设法让它工作,虽然这感觉很不对,但我现在有 3 个模型:Event、Job 和 APSchedulerJobsTable。最终模型基本上与 APScheduler apscheduler_jobs 的外观相匹配。不过一定有更好的方法来做到这一点。
from project import db
class Event(db.Model):
__tablename__ = "event"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
jobs = db.relationship('Job', backref='job_event')
class Job(db.Model):
__tablename__ = "job"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
apscheduler_job_id = db.Column(db.TEXT, db.ForeignKey('apscheduler_jobs.id'))
event_id = db.Column(db.Integer, db.ForeignKey('event.id'))
class APSchedulerJobsTable(db.Model):
# TODO: This feels bad man
__tablename__ = "apscheduler_jobs"
id = db.Column(db.TEXT, primary_key=True, autoincrement=True)
next_run_time = db.Column(db.REAL)
job_state = db.Column(db.TEXT)
好吧,两个解决方案——在我看来都不是很完美:
解决方案一,可能更干净 - 只需在作业 table 中有一个包含 aspscheduler_job_ids 的文本字段 - 虽然这不是外键但是一旦 aspscheduler_job ID 已知,就可以继续并将其存储在作业中 table 供以后参考
class Event(db.Model):
__tablename__ = "event"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
jobs = db.relationship('Job', backref='job_event')
class Job(db.Model):
__tablename__ = "job"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'))
apscheduler_job_id = db.Column(db.TEXT)
抓住这个是为了删除完整的数据库,你需要 运行 这包括删除非托管 table apscheduler_jobs
:
db.reflect()
db.drop_all()
方案二,将apschedulertable添加到model本身,然后设置外键:
class Event(db.Model):
__tablename__ = "event"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
jobs = db.relationship('Job', backref='job_event')
class Job(db.Model):
__tablename__ = "job"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'))
apscheduler_job_id = db.Column(db.TEXT, db.ForeignKey('apscheduler_jobs.id'))
class APSchedulerJobsTable(db.Model):
# TODO: This feels bad man
__tablename__ = "apscheduler_jobs"
id = db.Column(db.TEXT, primary_key=True, autoincrement=True)
next_run_time = db.Column(db.REAL)
job_state = db.Column(db.TEXT)
job = db.relationship('Job', backref='job_event')
我有一个 Python Flask 应用程序,使用 flask.ext.sqlalchemy
和 apscheduler.schedulers.background
。我已经创建了一个 JobStore 并获得了一个名为 apscheduler_jobs
的 table 具有以下字段:
|id |next_run_time|job_state|
------------------------------
|TEXT| REAL | TEXT |
我想将一个 SQLAlchemy 模型对象与 table 相关联,使用如下方式:
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
scheduler.add_jobstore('sqlalchemy', url=app.config['SQLALCHEMY_DATABASE_URI'])
class Event(db.Model):
__tablename__ = "event"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
jobs = db.relationship('scheduler', backref='apscheduler_jobs')
所以我想使用 APScheduler apscheduler_jobs 中的 table,然后将其与我的 Event 对象的外键相关联。最后一行基本上会中断,因为 "scheduler" 不是定义的 SQLAlchmey 模型
qlalchemy.exc.InvalidRequestError: When initializing mapper Mapper|Event|event, expression 'scheduler' failed to locate a name ("name 'scheduler' is not defined"). If this is a class name, consider adding this relationship() to the <class 'project.models.Event'> class after both dependent classes have been defined.
所以我认为我需要一个中间模型 class 称为 "job" 或其他东西,然后将其与 apscheduler_jobs 相关联,但这里的某些东西仍然感觉很糟糕 - 因为 APScheduler 正在制作这个 table up 我无法控制那里发生的事情 - 我应该担心吗?
编辑 1:
所以我创建了 2 个模型,一个 "Event" 然后一个 "Job","Job" 然后与 table apscheduler_jobs
class Job(db.Model):
__tablename__ = "job"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
apscheduler_job_id = db.Column(db.Integer, db.ForeignKey('apscheduler_jobs.id'))
event_id = db.Column(db.Integer, db.ForeignKey('event.id'))
问题是当我删除数据库并重新创建它时抛出错误:
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'job.apscheduler_job_id' could not find table 'apscheduler_jobs' with which to generate a foreign key to target column 'id'
现在我可以在我的数据库创建脚本中解决这个问题,但我还是觉得我做错了方法
EDIT2 我设法让它工作,虽然这感觉很不对,但我现在有 3 个模型:Event、Job 和 APSchedulerJobsTable。最终模型基本上与 APScheduler apscheduler_jobs 的外观相匹配。不过一定有更好的方法来做到这一点。
from project import db
class Event(db.Model):
__tablename__ = "event"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
jobs = db.relationship('Job', backref='job_event')
class Job(db.Model):
__tablename__ = "job"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
apscheduler_job_id = db.Column(db.TEXT, db.ForeignKey('apscheduler_jobs.id'))
event_id = db.Column(db.Integer, db.ForeignKey('event.id'))
class APSchedulerJobsTable(db.Model):
# TODO: This feels bad man
__tablename__ = "apscheduler_jobs"
id = db.Column(db.TEXT, primary_key=True, autoincrement=True)
next_run_time = db.Column(db.REAL)
job_state = db.Column(db.TEXT)
好吧,两个解决方案——在我看来都不是很完美:
解决方案一,可能更干净 - 只需在作业 table 中有一个包含 aspscheduler_job_ids 的文本字段 - 虽然这不是外键但是一旦 aspscheduler_job ID 已知,就可以继续并将其存储在作业中 table 供以后参考
class Event(db.Model):
__tablename__ = "event"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
jobs = db.relationship('Job', backref='job_event')
class Job(db.Model):
__tablename__ = "job"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'))
apscheduler_job_id = db.Column(db.TEXT)
抓住这个是为了删除完整的数据库,你需要 运行 这包括删除非托管 table apscheduler_jobs
:
db.reflect()
db.drop_all()
方案二,将apschedulertable添加到model本身,然后设置外键:
class Event(db.Model):
__tablename__ = "event"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
jobs = db.relationship('Job', backref='job_event')
class Job(db.Model):
__tablename__ = "job"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'))
apscheduler_job_id = db.Column(db.TEXT, db.ForeignKey('apscheduler_jobs.id'))
class APSchedulerJobsTable(db.Model):
# TODO: This feels bad man
__tablename__ = "apscheduler_jobs"
id = db.Column(db.TEXT, primary_key=True, autoincrement=True)
next_run_time = db.Column(db.REAL)
job_state = db.Column(db.TEXT)
job = db.relationship('Job', backref='job_event')