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] <mailto:[email protected]>. To post to this group, send email to [email protected] <mailto:[email protected]>.
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.
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import event

Base = declarative_base()


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


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)


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)


e = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(e)

session = Session(e)
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()

print ts_type

Reply via email to