Hi!
I have defined my models in Pyramid like this:

# 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))

What I am trying to do here is to find a specific row from Codes table 
(filter it by code_str) and get all related tables in return, but under the 
condition that Location table returns only the last row by timestamp, Voyage 
table must return only the last row by departure, and it must have all 
information from Definitions table.

I started to create a query from the scratch and came across something like 
this:

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)

but I have notice that when I iterate through my results (like for code, 
voyage in query) I am actually iterating every Voyage I get in return. In 
theory it is not a big problem for me but I am trying to construct some 
json response with basic information from Codes table which would include 
all possible Voyages (if any at all).
For example:

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,
}

Now, this seems a bit wrong because I don't like rewriting this code_data in 
each loop, so I put if code_data is not {} line here, but I suppose it 
would be much better (logical) to iterate in a way similar to this:

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,
}

So, to get only single Code in return (since I queried the db for that 
specific Code) which would then have all Voyages related to it, and of 
course, in each Voyage all other information related to Definition of the 
particular Unit...

Is my approach good at all in the first place, and how could I construct my 
query in order to iterate it in this second way?
Thanks for all the help!!!

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to