Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用SQLAlchemy在金字塔中创建具有少量相关表的查询_Python_Sql_Postgresql_Sqlalchemy_Pyramid - Fatal编程技术网

Python 使用SQLAlchemy在金字塔中创建具有少量相关表的查询

Python 使用SQLAlchemy在金字塔中创建具有少量相关表的查询,python,sql,postgresql,sqlalchemy,pyramid,Python,Sql,Postgresql,Sqlalchemy,Pyramid,我在金字塔中定义了几个这样的表: # coding: utf-8 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Integer, Float, DateTime, ForeignKey, ForeignKeyConstraint, String, Column from sqlalchemy.orm import scoped_session, sessionmaker, relati

我在金字塔中定义了几个这样的表:

# coding: utf-8
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Integer, Float, DateTime, ForeignKey, ForeignKeyConstraint, String, Column
from sqlalchemy.orm import scoped_session, sessionmaker, relationship, backref,
from zope.sqlalchemy import ZopeTransactionExtension

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()


class Codes(Base):
    __tablename__ = 'Code'
    __table_args__ = {u'schema': 'Locations'}

    id = Column(Integer, nullable=False)
    code_str = Column(String(9), primary_key=True)
    name = Column(String(100))

    incoming = relationship(u'Voyages', primaryjoin='Voyage.call == Codes.code_str', backref=backref('Code'))


class Locations(Base):
    __tablename__ = 'Location'
    __table_args__ = {u'schema': 'Locations'}

    unit_id = Column(ForeignKey(u'Structure.Definition.unit_id', ondelete=u'RESTRICT', onupdate=u'CASCADE'), primary_key=True, nullable=False)
    timestamp = Column(DateTime, primary_key=True, nullable=False)
    longitude = Column(Float)
    latitude = Column(Float)


class Voyages(Base):
    __tablename__ = 'Voyage'
    __table_args__ = (ForeignKeyConstraint(['unit_id', 'Voyage_id'], [u'Locations.Voyages.unit_id', u'Locations.Voyages.voyage_id'], ondelete=u'RESTRICT', onupdate=u'CASCADE'), {u'schema': 'Locations'}
    )

    uid = Column(Integer, primary_key=True)
    unit_id = Column(Integer)
    voyage_id = Column(Integer)
    departure = Column(ForeignKey(u'Locations.Code.code_str', ondelete=u'RESTRICT', onupdate=u'CASCADE'))
    call = Column(ForeignKey(u'Locations.Code.code_str', ondelete=u'RESTRICT', onupdate=u'CASCADE'))
    departure_date = Column(DateTime)

    voyage_departure = relationship(u'Codes', primaryjoin='Voyage.departure == Codes.code_str')
    voyage_call = relationship(u'Codes', primaryjoin='Voyage.call == Codes.code_str')


class Definitions(Base):
    __tablename__ = 'Definition'
    __table_args__ = {u'schema': 'Structure'}

    unit_id = Column(Integer, primary_key=True)
    name = Column(String(90))
    type = Column(ForeignKey(u'Structure.Type.id', ondelete=u'RESTRICT', onupdate=u'CASCADE'))

    locations = relationship(u'Locations', backref=backref('Definition'))
    dimensions = relationship(u'Dimensions', backref=backref('Definition'))
    types = relationship(u'Types', backref=backref('Definition'))
    voyages = relationship(u'Voyages', backref=backref('Definition'))


class Dimensions(Base):
    __tablename__ = 'Dimension'
    __table_args__ = {u'schema': 'Structure'}

    unit_id = Column(ForeignKey(u'Structure.Definition.unit_id', ondelete=u'RESTRICT', onupdate=u'CASCADE'), primary_key=True, nullable=False)
    length = Column(Float)


class Types(Base):
    __tablename__ = 'Type'
    __table_args__ = {u'schema': 'Structure'}

    id = Column(SmallInteger, primary_key=True)
    type_name = Column(String(255))
    type_description = Column(String(255))
string_to_search = request.matchdict.get('code')

sub_dest = DBSession.query(func.max(Voyage.departure).label('latest_voyage_timestamp'), Voyage.unit_id, Voyage.call.label('destination_call')).\
    filter(Voyage.call== string_to_search).\
    group_by(Voyage.unit_id, Voyage.call).\
    subquery()

query = DBSession.query(Codes, Voyage).\
    join(sub_dest, sub_dest.c.destination_call == Codes.code_str).\
    outerjoin(Voyage, sub_dest.c.latest_voyage_timestamp == Voyage.departure_date)
我在这里试图做的是从
code
表中找到一个特定的行(通过
code\u str
过滤它),并得到所有相关的表作为返回,但是在
Location
表只返回
timestamp
的最后一行的条件下,
航行
表必须仅返回出发时的最后一行,并且必须包含
定义
表中的所有信息

我从头开始创建查询,遇到如下情况:

# coding: utf-8
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Integer, Float, DateTime, ForeignKey, ForeignKeyConstraint, String, Column
from sqlalchemy.orm import scoped_session, sessionmaker, relationship, backref,
from zope.sqlalchemy import ZopeTransactionExtension

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()


class Codes(Base):
    __tablename__ = 'Code'
    __table_args__ = {u'schema': 'Locations'}

    id = Column(Integer, nullable=False)
    code_str = Column(String(9), primary_key=True)
    name = Column(String(100))

    incoming = relationship(u'Voyages', primaryjoin='Voyage.call == Codes.code_str', backref=backref('Code'))


class Locations(Base):
    __tablename__ = 'Location'
    __table_args__ = {u'schema': 'Locations'}

    unit_id = Column(ForeignKey(u'Structure.Definition.unit_id', ondelete=u'RESTRICT', onupdate=u'CASCADE'), primary_key=True, nullable=False)
    timestamp = Column(DateTime, primary_key=True, nullable=False)
    longitude = Column(Float)
    latitude = Column(Float)


class Voyages(Base):
    __tablename__ = 'Voyage'
    __table_args__ = (ForeignKeyConstraint(['unit_id', 'Voyage_id'], [u'Locations.Voyages.unit_id', u'Locations.Voyages.voyage_id'], ondelete=u'RESTRICT', onupdate=u'CASCADE'), {u'schema': 'Locations'}
    )

    uid = Column(Integer, primary_key=True)
    unit_id = Column(Integer)
    voyage_id = Column(Integer)
    departure = Column(ForeignKey(u'Locations.Code.code_str', ondelete=u'RESTRICT', onupdate=u'CASCADE'))
    call = Column(ForeignKey(u'Locations.Code.code_str', ondelete=u'RESTRICT', onupdate=u'CASCADE'))
    departure_date = Column(DateTime)

    voyage_departure = relationship(u'Codes', primaryjoin='Voyage.departure == Codes.code_str')
    voyage_call = relationship(u'Codes', primaryjoin='Voyage.call == Codes.code_str')


class Definitions(Base):
    __tablename__ = 'Definition'
    __table_args__ = {u'schema': 'Structure'}

    unit_id = Column(Integer, primary_key=True)
    name = Column(String(90))
    type = Column(ForeignKey(u'Structure.Type.id', ondelete=u'RESTRICT', onupdate=u'CASCADE'))

    locations = relationship(u'Locations', backref=backref('Definition'))
    dimensions = relationship(u'Dimensions', backref=backref('Definition'))
    types = relationship(u'Types', backref=backref('Definition'))
    voyages = relationship(u'Voyages', backref=backref('Definition'))


class Dimensions(Base):
    __tablename__ = 'Dimension'
    __table_args__ = {u'schema': 'Structure'}

    unit_id = Column(ForeignKey(u'Structure.Definition.unit_id', ondelete=u'RESTRICT', onupdate=u'CASCADE'), primary_key=True, nullable=False)
    length = Column(Float)


class Types(Base):
    __tablename__ = 'Type'
    __table_args__ = {u'schema': 'Structure'}

    id = Column(SmallInteger, primary_key=True)
    type_name = Column(String(255))
    type_description = Column(String(255))
string_to_search = request.matchdict.get('code')

sub_dest = DBSession.query(func.max(Voyage.departure).label('latest_voyage_timestamp'), Voyage.unit_id, Voyage.call.label('destination_call')).\
    filter(Voyage.call== string_to_search).\
    group_by(Voyage.unit_id, Voyage.call).\
    subquery()

query = DBSession.query(Codes, Voyage).\
    join(sub_dest, sub_dest.c.destination_call == Codes.code_str).\
    outerjoin(Voyage, sub_dest.c.latest_voyage_timestamp == Voyage.departure_date)
但是我注意到,当我迭代我的结果时(比如
对于代码,查询中的航程
),我实际上迭代了我得到的每个
航程
。理论上,这对我来说不是什么大问题,但我正试图用
代码
表中的基本信息构建一些json响应,其中包括所有可能的
航行
(如果有的话)。 例如:

code_data = {}
all_units = []

for code, voyage in query:
    if code_data is not {}:
        code_data = {
            'code_id': code.id,
            'code_str': code.code_str,
            'code_name': code.name,
        }

    single_unit = {
        'unit_id': voyage.unit_id,
        'unit_departure': str(voyage.departure_date) if voyage.departure_date else None,
    }
    all_units.append(single_unit)

return {
    'code_data':  exception.message if exception else code_data,
    'voyages': exception.message if exception else all_units,
}
现在,这似乎有点错误,因为我不喜欢在每个循环中重写这个
code\u数据
,所以我把
如果code\u数据不是{}
行放在这里,但我认为以类似于这样的方式迭代会更好(逻辑上):

for code in query:
    code_data = {
        'code_id': code.id,
        'code_str': code.code_str,
        'code_name': code.name,
    }
    for voyage in code.voyages:
        single_unit = {
            'unit_id': voyage.unit_id,
            'unit_departure': str(voyage.departure) if voyage.departure else None,
        }
        all_units.append(single_unit)

return {
    'code_data':  exception.message if exception else code_data,
}
因此,只获取单个
代码
(因为我查询了数据库中特定的
代码
),它将所有
航程
作为嵌套值,当然,在每个
航程中
与特定
单元的
定义
相关的所有其他信息

首先,我的方法是否很好?我如何构造查询以便以第二种方式进行迭代

我在Postgres数据库中使用Python 2.7.6、SQLAlchemy 0.9.7和Pyramid 1.5.1


谢谢

尝试更改外部查询,如下所示:

query = DBSession.query(Codes).options(contains_eager('incoming')).\
    join(sub_dest, sub_dest.c.destination_call == Codes.code_str).\
    outerjoin(Voyage, sub_dest.c.latest_voyage_timestamp == Voyage.departure_date)
如果出现问题,请尝试调用选项(…)部分,如下所示:

(...) .options(contains_eager(Codes.incoming)). (...)
这将导致返回一个
Codes
实例,其中包含可通过您定义的关系(
传入的
)访问的
Voyages
对象,因此您可以继续:

results = query.all()
for code in results:
    print code 
    # do something with code.incoming
    # actually, you should get only one code so if it proves to work, you should 
    # use query.one() so that in case something else than a single Code is returned,
    # an exception is thrown

当然,您需要导入,例如:
来自sqlalchemy.orm导入包含\u eager

感谢您的帮助!我只是想知道
包含\u eager('incoming')
包含\u eager(Codes.incoming)
之间的区别是什么?它在两种情况下都有效,但我只是好奇为什么第一种会产生最终的“问题”?坦率地说,我不知道。文档将第一个调用为“字符串版本[调用]”,第二个调用为“使用类绑定描述符的[版本]”。我确信它们是完全相同的(在它们所做的事情上),除了我想知道如果您有一个查询,其中两个或多个实体具有相同名称的关系,那么会发生什么情况。那么,字符串版本可能会模棱两可?我把它留给好奇的人:)很高兴它成功了!!!