2015-10-16 2 views
2

У меня есть приложение Python Flask с использованием flask.ext.sqlalchemy и apscheduler.schedulers.background. Я создал JobStore и получил таблицу с именем apscheduler_jobs это имеет следующие поля:Как связать JobStore APScheduler с SQLAlchemy (внешний ключ) - Python Flask

|id |next_run_time|job_state| 
------------------------------ 
|TEXT| REAL  | TEXT | 

Я хочу, чтобы связать объект SQLAlchemy модель для этой таблицы, используя что-то вроде этого:

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, а затем связать это с внешним ключом для моего объекта Event. Эта последняя линия будет в основном сломать, как «планировщик» не определен 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. 

Так что я думаю, что мне нужен Inbetween класс модели под названием «работа» или что-то, то отношение, что apscheduler_jobs, но что-то здесь все еще чувствует себя плохо - потому что APScheduler делает этот стол вверх, я не контролирую, что там происходит - должен ли я быть обеспокоен этим?

EDIT1: Так что я создал 2 модели, одно «событие», то один «Работа», в «Работа», то относится к столу 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'

Теперь я мог обойти, что в моем создании базы данных сценария, но опять же он все еще чувствует, как я DOI нг это неправильный путь

EDIT2 мне удалось заставить его работать, хотя это чувствует себя довольно неправильно, я в настоящее время есть 3 модели: событие, работа, и 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) 

ответ

1

Ok, два решения - ни на самом деле идеально IMO:

Решение Один, вероятно, более чистое - просто есть текстовое поле в таблице заданий, которая содержит aspscheduler_job_ids - это не является внешним ключ, хотя но как только aspscheduler_job ID известно, что можно идти вперед и сохранить его в таблице задания для последующего использования ссылки

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) 

Выгоды для этого один в порядке, чтобы понизиться полным дб вам нужно запустить й будет включать сбросив неуправляемого таблицу apscheduler_jobs:

db.reflect() 
db.drop_all() 

Решение Два, добавить таблицу apscheduler в самой модели, а затем настроить внешний ключ:

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')