5

我正在尝试编写包含如下记录的 Schedule 类:... session, base, engine declaration here...

class Schedule(Base):
    __tablename__ = 'schedule'
    id = Column(Integer, primary_key=True)
    # and here i need ref to Station class
    station_id = Column(Integer, ForeignKey('station.id'))
    station = relationship('Station') # Also tried Station
    arr_time = Column(Time)

    def __init__(self, station_name, arrive_time):
         self.metadata.create_all()
         self.arrive_time = arrive_time

         # And now I'm trying to find station object by a given name
         # and add ref to it in self.station. 
         # The selection of a station works properly here:
         station = session.query(Station).filter(Station.name == station_name).first()
         # But on this statement I get an error: None object has no method 'append'
         self.station.append(station)
         session.add(self)
         session.commit()

之后我实现了“站”类

class Station(Base):
    __tablename__ = 'stations'
    id = Column(Integer, primary_key=True)
    name = Column(String)

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

因此,当我尝试添加新的计划记录时,我收到一个错误:

AttributeError: 'NoneType' object has no attribute 'append' 

一对多的情况(第一类中的外键和第二类中的关系)正常工作。

我的代码有什么问题?

更新: 还尝试了文档中的示例:

engine = create_engine('sqlite:///:memory:')
Base = declarative_base(engine)
session = sessionmaker(bind=engine)()

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    child_id = Column(Integer, ForeignKey('child.id'))
    child = relationship("Child")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)


if __name__ == '__main__':
    Base.metadata.create_all()
    parent = Parent()
    session.add(parent)
    child = Child()
    session.add(child)
    print(hasattr(Parent, 'child'))
    print(hasattr(parent, 'child'))
    print(type(Parent.child))
    print(type(parent.child))

我得到:

 >>> True
 >>> True
 >>> <class 'sqlalchemy.orm.attributes.InstrumentedAttribute'>
 >>> <class 'NoneType'>
4

3 回答 3

4

I've got it)) The problem was that as default uselist flag in constructor of relationship is set for True. But - I don't really understand why it is not written in documentation - in the case of many-to-one relation this flag is set for False.

So, to solve my problem I simply have to change this:

station = relationship("Station", uselist=True)

or use in constructor:

self.station = station

This completely solves my problem.

于 2013-10-14T09:54:39.537 回答
2

我有一个类似的问题。我认为问题在于,在您添加和提交之前,关系不会被触发。

engine = create_engine('sqlite:///:memory:')
Base = declarative_base(engine)
session = sessionmaker(bind=engine)()

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    child_id = Column(Integer, ForeignKey('child.id'))
    child = relationship("Child")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)


if __name__ == '__main__':
    Base.metadata.create_all()
    parent = Parent()
    session.add(parent)
    child = Child()
    session.add(child)
    session.commit() # IMPORTANT: this is necessary for relationship to work
    print(hasattr(Parent, 'child'))
    print(hasattr(parent, 'child'))
    print(type(Parent.child))
    print(type(parent.child))

我添加的唯一行是

        session.commit() # IMPORTANT: this is necessary for relationship to work
于 2016-06-14T22:08:04.617 回答
0
station = session.query(Station).filter(Station.name == station.name).first()

self.station是无....

尝试使用调试器或只是print stationprint self.station

编辑:类变量范围:

类作用域变量有两种方式:

  1. 实例变量 - 使用 self 时,这称为实例变量,通过该类的每个实例,您将拥有该变量的副本。

  2. 类属性-在您的情况下,它是属于该类的 Schedule.station,而不是该类的实例。

请参阅有关命名空间的文档,它将解决您的问题。

于 2013-10-14T08:44:56.373 回答