피라미드에서 몇 관련 테이블과 쿼리를 생성 내가 정의한 몇 테이블 :SQLAlchemy의
# 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))
내가 여기서 뭘하려고하는 Codes
테이블에서 특정 행을 찾는 것입니다 (그것을 필터링 에 의해 code_str
) 모든 관련 테이블을 얻지 만 Location
테이블이 timestamp
에 의해 마지막 행만 반환하는 조건에서 에 의해 마지막 행만 반환해야하며 Definitions
의 모든 정보를 가져야합니다.
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)
하지만 난 내 결과 (for code, voyage in query
를 같은)을 반복 할 때 나는 반복하는에게 실제로 내가 할 모든 Voyage
임을 통지를 답례로. 이론적으로는 큰 문제는 아니지만 모든 가능한 경우를 포함하여 Codes
테이블의 기본 정보로 일부 json 응답을 구성하려고합니다. 예를 들어 :에 나는 각 루프에서이 code_data
를 재 작성 좋아하지 않기 때문에 지금
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,
}
이 조금 잘못된 것 같다, 그래서 여기 if code_data is not {}
라인을 넣어,하지만 난 그게 훨씬 더 (논리)이 될 것입니다 가정 다음 중첩 된 값으로 관련된 모든 Voyages
있을 것입니다 (나는 특정 Code
에 대한 DB를 조회 이후) 반환 만 단일 Code
를 얻기 위해, 그래서
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,
}
, 그리고이 유사한 방법으로 반복 물론, 각 Voyage
에 관한 기타 모든 정보 ...
내 접근 방식은 처음부터 좋았으며 두 번째 방식으로 내 쿼리를 반복 작성하려면 어떻게해야합니까?
저는 Postgres 데이터베이스와 함께 Python 2.7.6, SQLAlchemy 0.9.7 및 Pyramid 1.5.1을 사용하고 있습니다.
감사합니다.
감사합니다! 나는'contains_eager ('incoming')'과'contains_eager (Codes.incoming)'의 차이점을 궁금 할 뿐이니? 그것은 두 경우 모두에서 작동하지만 첫 번째 것이 궁극적 인 '문제'를 만드는 이유가 궁금합니다. – errata
솔직하게 말하면, 나는 모른다. 문서는 첫 번째 버전을 "문자열 버전 [호출 중]"이라고하고 두 번째 버전은 "클래스 바인딩 된 설명자를 사용하는 [버전]"을 호출합니다. 두 개 이상의 엔티티가 같은 이름으로 관계가있는 여러 엔티티가있는 쿼리를 사용하면 어떤 일이 발생하는지 궁금 할 때를 제외하고는 정확히 동일하다고 확신합니다. 아마도 문자열 버전은 모호 할 것입니다. 나는 호기심에 그것을두고 간다 :) 그것은 기뻤다! !! – PawelP