[Grok-dev] Modeling a class that extend from list() with megrok.rdb

Jeffrey D Peterson bgpete at gmail.com
Wed Oct 27 13:13:39 EDT 2010


I am a little confused to what you are trying to accomplish.

Maybe it would be better to define what you need it to do, and model that
vs. trying to equivocate things class by class, I realize you want to save
code but you are converting from object data to relational data, they aren't
always converted easily.

Extrapolating from what you have shown us it seems you are storing MyEntry
objects in extended python lists, correct?  I assume, that these lists are
stored in the ZODB for persistence.  

Now with relational data you essentially get back a list of dictionaries,
right?  Rows of key-value pairs.  With SQLAlchemy you can change that a
little to where you wind up with essentially a list of objects, where each
row is an object and the key-value pairs are properties of the object.

In each case, your "entries" are contained in a list.  With SQLAlchemy you
are closer as it's a list of objects, _and_ you can write methods easily to
access the objects.

If it needs to be sorted out into multiple named containers, then you need
to add that wrinkle, by adding a container id to the entry object and either
managing that by hand or by maintaining a table of container IDs	  

So either you'll end up with a query that looks at a container table and
joins the entries or you'll have an entries table that you can query for
only certain entries based on a container ID

This is what I think you are getting at, am I even close?

--
Jeffrey Peterson
bgpete3 at gmail.com


> -----Original Message-----
> From: grok-dev-bounces at zope.org [mailto:grok-dev-bounces at zope.org] On
> Behalf Of Hector Blanco
> Sent: Wednesday, October 27, 2010 9:06 AM
> Cc: grok-dev at zope.org
> Subject: Re: [Grok-dev] Modeling a class that extend from list() with
> megrok.rdb
> 
> Oh, now I see what you meant. Thanks!
> 
> But there's still a problem (sorry, I'm really new to this and I may
> have the concepts wrong):
> 
> The class I want it to attack the "my_containers_table" table is
>     class MyContainer(list)
> which currently extends from list (not rdb.Model).
> 
> Is there a way to have both functionalities? Do I have to go to
> multiple inheritance? ( class MyContainer(list, rdb.Model)   ).
> Wouldn't that be "dangerous"? (I have been thought to avoid multiple
> inheritance as the plague).
> 
> Do I have to do something like:
>    class MyContainer(rdb.Model):
>         def __init__(self):
>                self._list = list()
> 
> and use that self._list to store the data?
> 
> Thank you for your help!
> 
> 2010/10/26 Jeffrey D Peterson <bgpete at gmail.com>:
> >
> >
> > --
> > Jeffrey Peterson
> > bgpete3 at gmail.com
> >
> >> -----Original Message-----
> >> From: grok-dev-bounces at zope.org [mailto:grok-dev-bounces at zope.org]
> On
> >> Behalf Of Hector Blanco
> >> Sent: Tuesday, October 26, 2010 4:16 PM
> >> Cc: grok-dev at zope.org
> >> Subject: Re: [Grok-dev] Modeling a class that extend from list()
> with
> >> megrok.rdb
> >>
> >> Hi guys!
> >>
> >> Thank you for your answers.
> >>
> >> To Jeff Petterson>
> >>      That's doable, but I would like to avoid (if possible) creating
> >> raw MySQL queries. It turns out I am working with a pre-existent
> code,
> >> and the system doesn't really uses raw queries. It relies on
> >> sqlalchemy + megrok.rdb and I'd like to keep it consistent (once
> >> again, if possible). I have worked in other projects and I always
> >> prefer going to the lowest level possible (SQL queries "by hand")
> >> because I feel I can control them better, but not in this occasion.
> >
> > Who said anything about raw queries?  It's SQLAlchemy.
> >
> > This (straight SQLAlchemy):
> >
> >> my_containers_table = Table(
> >>       "my_containers_table",
> >>       metadata,
> >>       Column("id", Integer,  primary_key=True),
> >>       Column("my_entry_id", Integer,
> ForeignKey("my_entries_table.id"))
> >> )
> >
> > Is equivalent to this (megrok.rdb and SQLAlchemy):
> >
> > from megrok import rdb
> >
> > from sqlalchemy import Column
> > from sqlalchemy.types import Integer
> > from sqlalchemy.orm import relation
> >
> > class MyContainersTable(rdb.Model):
> >        rdb.metadata(metadata)
> >        rdb.tablename('my_containers_table') #this is optional but I
> like to
> > use it to be clear
> >
> >        id = Column('id', Integer, primary_key=True)
> >        my_entry_id = relation('my_entry_id', Integer,
> > ForeignKey('my_entries_table.id')
> >
> >
> > This is how megrok.rdb uses sqlalchemy to map tables to python
> classes.  It
> > uses sqlalchemy's declarative modeling and builds this table for you
> in
> > MySQL or if it already exists use rdb.reflected() to reflect it.
> >
> > Write all the methods you want to into the class to attack the table.
> >
> >>
> >> To Santiago Videla>
> >>      I took a look to the containers, but they seem to me just
> >> intermediate tables to define relationships, correct? Well... once
> >> again, I have to deal with the pre-existing code. The guys that
> >> developed it didn't use containers classes. The tables that were
> used
> >> as intermediate tables to specify relationships where declared in a
> >> lower level (only with sqlalchemy commands). To keep consistency
> with
> >> the existing code, I'd like to be able to define that intermediate
> >> tables myself.
> >>
> >> As I mentioned, the way I have it now is:
> >>
> >> class MyEntry(object):
> >>        def __init__(self):
> >>                self.field1 = “field1”
> >>                self.field2 = “field2”
> >>
> >> class MyContainer(list):
> >>        def __init__(self):
> >>                super(MyContainer,self).__init__()
> >>
> >>        def append(myEntry):
> >>                if isinstance(myEntry, MyEntry):
> >>                        super(MyContainer, self).append(myEntry)
> >>
> >>        def getByField1(self, field1):
> >>                for element in self:
> >>                        if element.field1 == field1:
> >>                                return element
> >>                return None
> >>
> >>        [ ... more useful methods ...]
> >>
> >> class MyClass(object):
> >>        def __init__(self):
> >>                self.container1 = MyContainer()
> >>                self.container2 = MyContainer()
> >>                self.anotherField = “hello world”
> >>        def getContainer1():
> >>                return self.container1
> >>        def getContainer2():
> >>                return self.container2
> >>
> >> I see clearly the "MyEntry" and "MyClass" classes descending from
> >> (rdb.Model). I also see clearly the intermediate table for
> >> MyContainer:
> >>
> >> #This would be the equivalent to a "rdb.Container", correct, Mr.
> >> Videla? Well... in the current system, it is done "by hand", like
> >> this:
> >> my_containers_table = Table(
> >>       "my_containers_table",
> >>       metadata,
> >>       Column("id", Integer,  primary_key=True),
> >>       Column("my_entry_id", Integer,
> ForeignKey("my_entries_table.id"))
> >> )
> >>
> >> but I don't know how to link the MyContainer(list) object with
> >> my_containers_table (and from there with MyClass) :-(
> >>
> >> I guess MyClass could be modeled with something like:
> >>
> >> class MyClass(rdb.Model):
> >>       rdb.metadata(metadata)
> >>       rdb.tablename("my_class_table")
> >>       id = Column("id", Integer, primary_key=True)
> >>       anotherField =  Column("another_field", String(16))
> >>       container1 = Column("container_1", Integer,
> >> ForeignKey("my_containers_table.id")),
> >>       container2 = Column("container_2", Integer,
> >> ForeignKey("my_containers_table.id"))
> >>
> >> But now, how do I establish the relationship between
> >> MyClass.container1 or MyClass.container2 with "my_containers_table"?
> >> On one hand, I want MyClass.container1 and MyClass.container2 to be
> >> foreign keys, but on the other, I want them to be instances of
> >> MyContainer(list)... And that's where I start banging my head on the
> >> wall :-)
> >>
> >> I know... the existing code is a complicated mix between megrok and
> >> sqlalchemy... but that's what I have to deal with (although if it
> >> needs to be changed because there's no other way, well... I can do
> it)
> >>
> >> Thank you again
> >>
> >> 2010/10/26 Santiago Videla <santiago.videla at gmail.com>:
> >> > Hi, I am not working with megrok.rdb these days neither with
> grok...
> >> but,
> >> > did you see rdb.Container and rdb.QueryContainer? I am not sure,
> but
> >> maybe
> >> > it could help you with this.
> >> > Regards,
> >> >
> >> > On Mon, Oct 25, 2010 at 7:02 PM, Hector Blanco
> >> <white.lists at gmail.com>
> >> > wrote:
> >> >>
> >> >> Hi list!
> >> >>
> >> >> I am trying to migrate my application from ZopeDB to MySql. I am
> >> using
> >> >> megrok.rdb.
> >> >>
> >> >> I have a class which inherits from list() and has a few extra
> >> methods.
> >> >>
> >> >> That class acts as a container of other classes and is used (as
> an
> >> >> attribute) in other classes as well:
> >> >>
> >> >> class MyEntry(object):
> >> >>        def __init__(self):
> >> >>                self.field1 = “field1”
> >> >>                self.field2 = “field2”
> >> >>
> >> >> class MyContainer(list):
> >> >>        def __init__(self):
> >> >>                super(MyContainer,self).__init__()
> >> >>
> >> >>        def append(myEntry):
> >> >>                if isinstance(myEntry, MyEntry):
> >> >>                        super(MyContainer, self).append(myEntry)
> >> >>
> >> >>        def getByField1(self, field1):
> >> >>                for element in self:
> >> >>                        if element.field1 == field1:
> >> >>                                return element
> >> >>                return None
> >> >>
> >> >>        [ ... more useful methods ...]
> >> >>
> >> >> class MyClass(object):
> >> >>        def __init__(self):
> >> >>                self.container1 = MyContainer()
> >> >>                self.container2 = MyContainer()
> >> >>                self.anotherField = “hello world”
> >> >>        def getContainer1():
> >> >>                return self.container1
> >> >>        def getContainer2():
> >> >>                return self.container2
> >> >>
> >> >> I don't really know how to model this with megrok.rdb. I kind of
> see
> >> >> clearly (although I may be totally wrong) that MyEntry and
> MyClass
> >> >> should extend from rdb.Model and each of them should be stored in
> a
> >> >> table, but I don't really know what to do with “MyContainer”. I'd
> >> like
> >> >> to keep it inheriting from list, but I don't know how to model
> that.
> >> >> It really only needs to be an association between [id,
> >> id_of_my_entry]
> >> >> (relationship 1:N). In MyClass, each of the containers would get
> an
> >> id
> >> >> and then, if I want to get the “MyEntries” that are in
> container1, I
> >> >> just need to get the MyEntries who are linked to that id.
> >> >>
> >> >> 
 but I have no idea about how to implement that... Any hint I
> could
> >> >> get would be deeply appreciated.
> >> >>
> >> >> Thank you in advance!
> >> >> _______________________________________________
> >> >> Grok-dev mailing list
> >> >> Grok-dev at zope.org
> >> >> https://mail.zope.org/mailman/listinfo/grok-dev
> >> >
> >> >
> >> >
> >> > --
> >> > Santiago Videla
> >> > http://www.linkedin.com/in/svidela
> >> >
> >> > Sigue la mata dando de que hablar siempre abajo y a la izquierda
> >> donde el
> >> > pensamiento que se hace corazón resplandece con la palabra
> sencilla y
> >> > humilde que l at s tod at s somos.
> >> >
> >> _______________________________________________
> >> Grok-dev mailing list
> >> Grok-dev at zope.org
> >> https://mail.zope.org/mailman/listinfo/grok-dev
> >
> >
> _______________________________________________
> Grok-dev mailing list
> Grok-dev at zope.org
> https://mail.zope.org/mailman/listinfo/grok-dev



More information about the Grok-dev mailing list