[storm] Implementing auto add parent

James Henstridge james at jamesh.id.au
Thu Feb 11 12:46:26 GMT 2010


On Thu, Feb 11, 2010 at 7:45 PM, Eduardo Willians <edujurista at gmail.com> wrote:
> After a long long time without asking, here i am again.
>
> Sorry, if my question is stupid or my code is stupid.
>
> <code>
>
> class Oper(object):
>
>    __storm_table__ = "root.oper"
>
>    id = RawStr(primary=True)
>
>    date_time = DateTime()
>    operator = Int()
>    order = Int()
>    enrollment = Reference(operator, Enrollment.id)
>
>
>    def __init__(self, store, operator, date_time=None, auto_add=True):
>        self.id = None if store is None else self._increment_id(store)
>        self.operator = operator
>        self.date_time = date_time or datetime.datetime.now()
>        self._store = store
>        if auto_add:
>            self.add_self_commit()
>
>    def _increment_id(self, store):
>        order = self.__class__.order
>        last = store.find(self.__class__).order_by(order).last()
>        order = 1 if not last else last.order
>
>        oper = store.find(Oper, order=order).one()
>        oper_id = oper.id if oper else None
>        return routines.smart_id(oper_id)
>
>    def add_self_commit(self):
>        if self._store is None:
>            raise Exception('self._store cannot be None')
>        self._store.add(self)
>        self._store.commit()
>
>
> # Another file
>
>
> from share.models.root.tables import Oper
>
> class Session(object):
>    __storm_table__ = "financial.session"
>    id = RawStr(primary=True)
>    initial = Float()
>    # Refs
>    oper = Reference(id, Oper.id)
>
>    def __init__(self, root, operator, initial, date_time=None,
>                 add_oper=True):
>        oper = Oper(root, operator, date_time, add_oper)
>        self.id = oper.id
>        self.initial = initial
>
> </code>
>
>
> Here is the small problem. When I try this:
>
>
> <code>
>
> financial.add(Session(root, 5, 123.4))
> financial.commit( )
> # Then I get this:
>
>  File "/usr/lib/python2.6/dist-packages/storm/database.py", line 325,
> in _check_disconnect
>    return function(*args, **kwargs)
> IntegrityError: ERRO:  inserção ou atualização em tabela "session"
> viola restrição de chave estrangeira "session_id_fkey"
> DETAIL:  Chave (id)=(AAE) não está presente na tabela "oper".
>
> # Transalating:
>
> ERROR: Insertion or updating in table "session" violates foreign key
> constraint "session_id_fkey"
> DETAIL: Key (id)=(AAE) is not present at table "oper"
>
> </code>
>
> So, instead, I have to do this to work around:
>
> <code>
>
> financial.add(Session(root, 5, 123.4))
> financial.flush( )
> financial.commit( )
>
> </code>
>
> It's ok, but I dont want to have to command "financial.flush( )" on
> every part of code to commit an adding.

So, the underlying problem here is that Storm doesn't know that the
Session record you've created depends on the Oper record.  The
"self.id = oper.id" statement just looks like an assignment.

You might be able to fix this by using the reference to set self.id:
    self.oper = oper

The reference code will make sure that oper is then flushed first

>
> I neither want to first add a new 'Oper' table and after add a new
> 'Session' table because this wouldnt be useful, since I'm planning to
> make the same formula work to many other new tables.
>
> I also could create a "store" arg on __init__( ) at "Session" class
> and force a "store.flush( )". But I really don't think this would be
> right, something tells me that just send "store" as arg to the
> table-class would not be tha best way.
>
> There are other little hacks I could do to make it work, but it would
> not be the stormic way.
>
> And the final question is: Is there a stormic way to implement that
> heritance, so that I could make "child" auto-add a "parent" object
> without I have to make a "store.flush( )"?

In general, the answer is to use references.  If you're in a situation
where that isn't possible, then explicitly using the
store.add_flush_order() method might help (although that needs a
store).


James.



More information about the storm mailing list