Thank you so *much* for the quick and detailed reply Michael, worked like a
charm!
Haha, yes, I'm not really using Numpy (just a standard import, hehe).
On a sidenote, SQLAlchemy is one of the most complex and impressive
libraries I've ever seen, and the documentation is beyond words - so thank
you again!
Best, Victor
Den måndag 27 juli 2015 kl. 17:26:40 UTC+2 skrev Michael Bayer:
>
>
>
> On 7/27/15 10:56 AM, Victor Tingström wrote:
>
> Hey guys! First off, thank you for the library. Now to the problem, I'm
> currently trying to implement a simple timeseries database using
> `SQLAlchemy`. And so far I've seen the need for the following classes;
> First off is the `Platform` class (which is the highest in the hierarchy)
>
>
> OK, it's (mostly) runnable code, so I can just cut and paste (and cut out
> numpy, ecch !) and run, great.
>
> First thing, localize to where it is actually breaking, use constraints:
>
> class TimeseriesTypeORM(Base):
> __tablename__ = 'timeseriestypes'
>
> platform_id = Column(Integer, ForeignKey('platforms.platform_id'),
> nullable=False)
> # ...
>
> now we see the problem:
>
> <stacktrace>
> sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL
> constraint failed: timeseriestypes.platform_id [SQL: u'INSERT INTO
> timeseriestypes (platform_id, fund_id, ts_type_name) VALUES (?, ?, ?)']
> [parameters: (None, 1, 'spot')]
>
>
> so why is that. I'm looking around, and I don't see any relationships to
> TimeseriesTypeORM linked to Platform, so that would be why.
>
> Platform is only linked to FundORM, and that goes to TimeseriesTypeORM.
> So you either need to add another relationship, or use flush events to
> double up the timeseriestypes.platform_id value. The latter might be
> tricky because it might not fire off at the right time, so lets use
> relationship which makes sure everything is done in the right order.
> Let's use an append event to make the association automatic also:
>
> class FundORM(Base):
> __tablename__ = 'funds'
>
> fund_id = Column(Integer, primary_key=True)
> platform_id = Column(Integer, ForeignKey('platforms.platform_id'))
> fund_name = Column(String, unique=True)
>
> ts_types = relationship('TimeseriesTypeORM', backref='fund')
>
> def __init__(self, fund_name):
> self.fund_name = fund_name
>
> def __repr__(self):
> return "<Fund name('%s'), Platform ID('%s')>" % (
> self.fund_name, self.platform_id)
>
>
> @event.listens_for(FundORM.ts_types, "append")
> def append_ts_type(target, value, initiator):
> if target.platform is None:
> raise ValueError("FundORM has no PlatformORM assigned!")
> value.platform = target.platform
>
>
> class TimeseriesTypeORM(Base):
> __tablename__ = 'timeseriestypes'
>
> platform_id = Column(Integer, ForeignKey('platforms.platform_id'))
> fund_id = Column(Integer, ForeignKey('funds.fund_id'))
> ts_type_id = Column(Integer, primary_key=True)
> ts_type_name = Column(String)
>
> timeseries = relationship('TimeseriesORM', backref='ts_type')
>
> platform = relationship("PlatformORM")
>
> def __init__(self, ts_type_name=None):
> self.ts_type_name = ts_type_name
>
> def __repr__(self):
> return "<Type('%s'), Fund ID('%s'), Platform ID('%s')>" % (
> self.ts_type_name, self.fund_id, self.platform_id)
>
>
> now we run the same code and we get:
>
> SELECT timeseriestypes.platform_id AS timeseriestypes_platform_id,
> timeseriestypes.fund_id AS timeseriestypes_fund_id,
> timeseriestypes.ts_type_id AS timeseriestypes_ts_type_id,
> timeseriestypes.ts_type_name AS timeseriestypes_ts_type_name
> FROM timeseriestypes
> WHERE timeseriestypes.ts_type_id = ?
> 2015-07-27 11:22:35,956 INFO sqlalchemy.engine.base.Engine (1,)
> <Type('spot'), Fund ID('1'), Platform ID('1')>
>
>
>
> see attached.
>
>
>
>
>
>
>
>
> import numpy as np
> import pandas as pd
> import datetime
> from sqlalchemy import create_engine, Column, Integer, String, Float,
> ForeignKey, TIMESTAMP
> from sqlalchemy.ext.declarative import declarative_base
> from sqlalchemy.orm import sessionmaker, relation, backref
>
> engine = create_engine('sqlite:///:memory:', echo=False)
> Base = declarative_base()
> Session = sessionmaker(bind=engine)
> session = Session()
>
> class PlatformORM(Base):
> __tablename__ = 'platforms'
>
> platform_id = Column(Integer, primary_key=True)
> platform_name = Column(String, unique=True)
>
> subfunds = relationship('FundORM', backref='platform')
>
> def __init__(self, platform_name):
> self.platform_name = platform_name
>
> def __repr__(self):
> return "<Platform(name = '%s')>" % self.platform_name
>
>
> Next, comes the `FundORM` class, which is linked to the `PlatformORM`
> class. Such that an instance of `PlatformORM` can have several subfunds.
>
> class FundORM(Base):
> __tablename__ = 'funds'
>
> fund_id = Column(Integer, primary_key=True)
> platform_id = Column(Integer, ForeignKey('platforms.platform_id'))
> fund_name = Column(String, unique=True)
>
> ts_types = relationship('TimeseriesTypeORM', backref='fund')
>
> def __init__(self, fund_name):
> self.fund_name = fund_name
>
> def __repr__(self):
> return "<Fund name('%s'), Platform ID('%s')>" %
> (self.fund_name, self.platform_id)
>
> Using only these two classes it's easy to link them. However, I now wish
> to add another class called `TimeseriesTypeORM`, which is linked to
> `FundORM` and describes the different types of timeseries that `FundORM`
> has - it could for example be returns or spot price. This is defined such as
>
> class TimeseriesTypeORM(Base):
> __tablename__ = 'timeseriestypes'
>
> platform_id = Column(Integer, ForeignKey('platforms.platform_id'))
> fund_id = Column(Integer, ForeignKey('funds.fund_id'))
> ts_type_id = Column(Integer, primary_key=True)
> ts_type_name = Column(String)
>
> timeseries = relationship('TimeseriesORM', backref='ts_type')
>
> def __init__(self, ts_type_name=None):
> self.ts_type_name = ts_type_name
>
> def __repr__(self):
> return "<Type('%s'), Fund ID('%s'), Platform ID('%s')>" %
> (self.ts_type_name, self.fund_id, self.platform_id)
>
> Furthermore, I'd like to create another class called `TimeseriesORM`,
> which is linked to `TimeseriesTypeORM`, containing the actual data of the
> timeseries. The class is defined as
>
> class TimeseriesORM(Base):
> __tablename__ = 'timeseries'
>
> platform_id = Column(Integer, ForeignKey('platforms.platform_id'))
> fund_id = Column(Integer, ForeignKey('funds.fund_id'))
> ts_type_id = Column(Integer,
> ForeignKey('timeseriestypes.ts_type_id'))
> ts_id = Column(Integer, primary_key=True)
>
> date = Column(TIMESTAMP)
> value = Column(Float)
>
> def __init__(self, date=None, value=None):
> self.date = date
> self.value = value
>
> def __repr__(self):
> return "<Date('%s'), Fund ID('%s')>" % (self.date,
> self.fund_id)
>
> As an example, assume that we have a platform called `ABC`, and that
> `ABC` has a fund called `DBE`, where `DBE` in turn has data for spot prices
> which is to be added. Creating the platform, fund and timeseries type then
> yields
>
> platform = PlatformORM('ABC')
> fund = FundORM('DBE')
> platform.subfunds += [fund]
>
> ts_type = TimeseriesTypeORM('spot')
> fund.ts_types += [ts_type]
>
> session.add_all([platform, fund, ts_type])
> session.commit()
>
> I can run the above code just fine. However, if I try to view `ts_type`,
> It'll show
>
> <Type('spot'), Fund ID('1'), Platform ID('None')>,
>
> where `Platform ID` should be 1. However, printing `ts_type.fund` will
> show me the correct platform ID. I really can't figure out where I'm going
> wrong - but a guess is somewhere in the relation for `FundORM`. Do you guys
> have any ideas? It's kinda important to have the `platform_id` and
> `fund_id` as keys in `TimeseriesORM`. Thanks! // Victor
>
> --
> 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 [email protected] <javascript:>.
> To post to this group, send email to [email protected]
> <javascript:>.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.
>
>
>
--
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.