sqlalchemy InvalidRequestError:陈旧的关联代理,父对象已超出范围

时间:2016-02-19 20:40:53

标签: python-3.x sqlalchemy

我对sqlalchemy很新。我在网上搜索过,无法在论坛或sqlalchemy文档中找到任何有用的信息。

我在: Python 3.4 sqlalchemy 1.0.11

以下是相关的代码段:

models.py

from sqlalchemy import Table, Column, ForeignKey, Integer, String, Date, Numeric, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from sqlalchemy.ext.associationproxy import association_proxy

Base = declarative_base()

emp_exemptions_table = Table('emp_exemptions', Base.metadata,
    Column('employee_id',
           Integer,
           ForeignKey('employee.id'),
           primary_key=True),
    Column('exemptReasons_id',
           Integer,
           ForeignKey('exemptReasons.id'),
           primary_key=True)
)

current_exemptions_table = Table('current_exemptions', Base.metadata,
    Column('exemption_id',
           Integer,
           ForeignKey('exemption.id'),
           primary_key=True),
    Column('exemptReasons_id',
           Integer,
           ForeignKey('exemptReasons.id'),
           primary_key=True)
)


class ExemptReasons(Base):
    __tablename__ = 'exemptReasons'
    id = Column(Integer, primary_key=True)
    text = Column('exemptReasons',
                  String(30),
                  nullable=True)

    def __init__(self, text):
        self.text = text

class Employee(Base):
    __tablename__ = 'employee'
    id = Column(Integer, primary_key=True)
    eid = Column(String(8), nullable=False)
    hours = Column(Numeric(), nullable=False)
    exempt = Column(Boolean(), nullable=False)
    exempt_reasons = relationship(ExemptReasons,
                                  secondary=lambda: emp_exemptions_table)
    as_of_date = Column(Date())

    # proxy the 'exempt_reason' attribute from the 'exempt_reasons' relationship
    reasons = association_proxy('exempt_reasons', 'text')


class CurrentExemption(Base):
    __tablename__ = 'exemption'
    id = Column(Integer, primary_key=True)
    eid = Column(String(8), nullable=False)
    effective_date = Column(Date())
    exempt = Column(Boolean(), nullable=False)
    exempt_reasons = relationship(ExemptReasons,
                                  secondary=lambda: current_exemptions_table)
    # proxy the 'exempt_reason' attribute from the 'exempt_reasons' relationship
    reasons = association_proxy('exempt_reasons', 'text')

engine = create_engine('sqlite:///sqldb_example.db')

Base.metadata.create_all(engine)

相关功能

def determine_eligibility_changes(self, elig):

    engine = create_engine('sqlite:///sqldb_example.db')
    Base.metadata.bind = engine
    DBSession = sessionmaker(bind=engine)
    session = DBSession()

    student_reason = session.query(ExemptReasons).filter_by(text='Student Rule 3121(b)(10)').first()

    new_exemptions = []

    for e in elig:
        current_elig = session.query(Employee).filter_by(eid=e['eid']).first()  #todo: add time filter

        if current_elig.reasons:
            new_elig_reasons = current_elig.reasons
        else:
            new_elig_reasons = []

        if e['eligible']:

            if current_elig.exempt:
                if not (student_reason.text in current_elig.reasons):
                    new_elig_reasons.append(student_reason.text)
            else:
                new_elig_reasons.append(student_reason.text)
        else:  # not eligible now

            if current_elig.exempt:
                if student_reason.text in current_elig.reasons:
                    new_elig_reasons.remove(student_reason.text)
        e['exempt_reasons'] = new_elig_reasons

        new_exemptions.append(e)

    session.close()
    return new_exemptions


def store_current_eligibility(self, lines):
    engine = create_engine('sqlite:///sqldb_example.db')
    Base.metadata.bind = engine
    DBSession = sessionmaker(bind=engine)
    session = DBSession()
    for x in lines:
        new_eligibility = CurrentExemption(eid=x['eid'],
                                           effective_date=datetime.today(),  
                                           exempt=x['eligible'],
                                           reasons=x['exempt_reasons'],
                                           )

        session.add(new_eligibility)
    session.commit()

回溯

Traceback (most recent call last):
  File "start_calculator.py", line 5, in <module>
    app.run()
  File "/Users/hayne/bitbucket/APP005/app005/main_calculator.py", line 42, in run
    EligibilityCalculator.store_current_eligibility(self, new_list)
  File "/Users/hayne/bitbucket/APP005/app005/calculator/eligibility.py", line 134, in store_current_eligibility
    reasons=x['exempt_reasons'],
  File "<string>", line 4, in __init__
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/orm/state.py", line 306, in _initialize_instance
    manager.dispatch.init_failure(self, args, kwargs)
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 183, in reraise
    raise value
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/orm/state.py", line 303, in _initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/ext/declarative/base.py", line 649, in _declarative_constructor
    setattr(self, k, kwargs[k])
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/ext/associationproxy.py", line 283, in __set__
    self._set(proxy, values)
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/ext/associationproxy.py", line 352, in _set
    proxy.extend(values)
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/ext/associationproxy.py", line 617, in extend
    for v in values:
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/ext/associationproxy.py", line 604, in __iter__
    for member in self.col:
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/ext/associationproxy.py", line 509, in <lambda>
    col = property(lambda self: self.lazy_collection())
  File "/Users/hayne/.virtualenvs/APP005/lib/python3.4/site-packages/sqlalchemy/ext/associationproxy.py", line 465, in __call__
    "stale association proxy, parent object has gone out of "
sqlalchemy.exc.InvalidRequestError: stale association proxy, parent object has gone out of scope

所以当我运行它时,当我尝试填充m2m键的原因时,它就会出现错误。它确实超过了第一条记录的提交,并在第二条记录上轰炸。第一个记录在列表中有一个值,但第二个记录没有值。我已将空列表存储到代码中其他位置的关系字段中,因此我不认为这是问题所在。问题是我如何从determine_eligibility_changes中的列表中删除元素?我不能简单地从列表中删除它吗?是否需要做其他事情?

0 个答案:

没有答案