SQLAlchemy-AttributeError:_reverse_property

Awe*_*ebb 6 python sqlalchemy python-3.x

我在工作和学习SQLALCHEMY时遇到了一些麻烦,我认为问题与关系中的back_populates有关,但我无法对此进行说明。您能指出我正确的方向吗?

这些表已成功创建,并且在我尝试创建新的MailProvider之前,一切似乎都井然有序,这会导致此错误:

Traceback (most recent call last):
  File "C:/Users/Music/.PyCharm2016.2/config/scratches/scratch_7.py", line 71, in <module>
    gmail = MailProvider(service_provider="gmail.com")
  File "<string>", line 2, in __init__
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\orm\instrumentation.py", line 347, in _new_state_if_none
    state = self._state_constructor(instance, self)
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\util\langhelpers.py", line 754, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\orm\instrumentation.py", line 177, in _state_constructor
    self.dispatch.first_init(self, self.class_)
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\event\attr.py", line 256, in __call__
    fn(*args, **kw)
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\orm\mapper.py", line 2872, in _event_on_first_init
    configure_mappers()
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\orm\mapper.py", line 2768, in configure_mappers
    mapper._post_configure_properties()
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\orm\mapper.py", line 1708, in _post_configure_properties
    prop.init()
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\orm\interfaces.py", line 183, in init
    self.do_init()
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\orm\relationships.py", line 1632, in do_init
    self._generate_backref()
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\orm\relationships.py", line 1866, in _generate_backref
    self._add_reverse_property(self.back_populates)
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\orm\relationships.py", line 1574, in _add_reverse_property
    other._reverse_property.add(self)
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\util\langhelpers.py", line 840, in __getattr__
    return self._fallback_getattr(key)
  File "C:\Users\Music\mailtesterV2\lib\site-packages\sqlalchemy\util\langhelpers.py", line 818, in _fallback_getattr
    raise AttributeError(key)
AttributeError: _reverse_property
Run Code Online (Sandbox Code Playgroud)

我的代码:

from sqlalchemy import Column, ForeignKey, Integer, String, Boolean, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy import create_engine

engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)

Base = declarative_base()

class MailProvider(Base):
    __tablename__ = 'mail_provider'

    id = Column(Integer, primary_key=True)
    service_provider = Column(String(250), nullable=False)

    imap_server = Column(String(250))
    imap_server_port = Column(Integer)
    imap_server_ssl = Column(String(250))
    imap_server_port_ssl = Column(Integer)
    imap_server_use_tls = Column(Boolean)

    smtp_server = Column(String(250))
    smtp_server_port = Column(Integer)
    smtp_server_ssl = Column(String(250))
    smtp_server_port_ssl = Column(Integer)
    smtp_server_use_tls = Column(Boolean)

class MailAccount(Base):
    __tablename__ = "mail_account"

    id = Column(Integer, primary_key=True)
    email_address = Column(String(250), nullable=False)
    imap_username = Column(String(250), nullable=False)
    imap_password = Column(String(250), nullable=False)
    smtp_username = Column(String(250), nullable=False)
    smtp_password = Column(String(250), nullable=False)
    provider_id = Column(Integer, ForeignKey('mail_provider.id'), nullable=False)
    provider = relationship("MailProvider", back_populates="service_provider")
    account_owner = Column(String(250), nullable=False)

class SentMail(Base):
    __tablename__ = "sent_mail"

    id = Column(Integer, primary_key=True)
    mail_uuid = Column(String(36), nullable=False)
    time_sent = Column(DateTime(timezone=True), nullable=False)
    sent_from_id = Column(Integer, ForeignKey('mail_account.id'), nullable=False)
    sent_from = relationship("MailAccount", back_populates="email_address")
    sent_to = Column(String(250), nullable=False)
    msg_subject = Column(String(250))
    msg_body = Column(String)
    send_status = Column(String(500))

class ReceivedMail(Base):
    __tablename__ = "received_mail"

    id = Column(Integer, primary_key=True)
    sent_mail_id = Column(Integer, ForeignKey('sent_mail.id'), nullable=False)
    sent_mail = relationship("SentMail", back_populates="mail_uuid")
    time_received = Column(DateTime(timezone=True), nullable=False)


MailProvider.accounts = relationship("MailAccount", back_populates="provider", order_by="MailAccount.id")
MailAccount.mails_sent = relationship("SentMail", back_populates="mail_uuid", order_by="SentMail.time_sent")
SentMail.received_mails = relationship("RecievedMail", back_populates="received_time", order_by="RecievedMail.received_time")

Base.metadata.create_all(engine)
session = Session()
gmail = MailProvider(service_provider="gmail.com")

session.add(gmail)
session.commit()
Run Code Online (Sandbox Code Playgroud)

Awe*_*ebb 6

关系back_populate引用其他关系,而不是列。

修改后的代码:

from sqlalchemy import Column, ForeignKey, Integer, String, Boolean, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy import create_engine

engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)

Base = declarative_base()

class MailProvider(Base):
    __tablename__ = 'mail_provider'

    id = Column(Integer, primary_key=True)
    service_provider = Column(String(250), nullable=False)

    imap_server = Column(String(250))
    imap_server_port = Column(Integer)
    imap_server_ssl = Column(String(250))
    imap_server_port_ssl = Column(Integer)
    imap_server_use_tls = Column(Boolean)

    smtp_server = Column(String(250))
    smtp_server_port = Column(Integer)
    smtp_server_ssl = Column(String(250))
    smtp_server_port_ssl = Column(Integer)
    smtp_server_use_tls = Column(Boolean)

    accounts = relationship("MailAccount", back_populates="provider")

class MailAccount(Base):
    __tablename__ = "mail_account"

    id = Column(Integer, primary_key=True)
    email_address = Column(String(250), nullable=False)
    imap_username = Column(String(250), nullable=False)
    imap_password = Column(String(250), nullable=False)
    smtp_username = Column(String(250), nullable=False)
    smtp_password = Column(String(250), nullable=False)
    provider_id = Column(Integer, ForeignKey('mail_provider.id'), nullable=False)
    provider = relationship("MailProvider", back_populates="accounts")
    account_owner = Column(String(250), nullable=False)
    mails_sent = relationship("SentMail", back_populates="sent_from", order_by="SentMail.time_sent")

class SentMail(Base):
    __tablename__ = "sent_mail"

    id = Column(Integer, primary_key=True)
    mail_uuid = Column(String(36), nullable=False)
    time_sent = Column(DateTime(timezone=True), nullable=False)
    sent_from_id = Column(Integer, ForeignKey('mail_account.id'), nullable=False)
    sent_from = relationship("MailAccount", back_populates="mails_sent")
    sent_to = Column(String(250), nullable=False)
    msg_subject = Column(String(250))
    msg_body = Column(String)
    send_status = Column(String(500))
    received_mails = relationship("ReceivedMail", back_populates="sent_mail", order_by="ReceivedMail.time_received")

class ReceivedMail(Base):
    __tablename__ = "received_mail"

    id = Column(Integer, primary_key=True)
    sent_mail_id = Column(Integer, ForeignKey('sent_mail.id'), nullable=False)
    sent_mail = relationship("SentMail", back_populates="received_mails")
    time_received = Column(DateTime(timezone=True), nullable=False)

Base.metadata.create_all(engine)
session = Session()
gmail = MailProvider(service_provider="gmail.com")

session.add(gmail)
session.commit()
Run Code Online (Sandbox Code Playgroud)