has_many_through

8 views
Skip to first unread message

Walter Cruz

unread,
Aug 16, 2007, 2:33:43 PM8/16/07
to sqle...@googlegroups.com
Hi all!
I can't find nothing similitar to active record has_many_through in
Elixir. I need a many to many relashionship, but with a datetime
column in the relashiongip table. How can I do that?

[]'s
- Walter

Jonathan LaCour

unread,
Aug 16, 2007, 4:03:37 PM8/16/07
to sqle...@googlegroups.com
Walter Cruz wrote:

We don't have the exact equivalent for this right now, but its
definitely something I want to add. You can get really close to this
already. Here is an example:


from elixir import *
from datetime import datetime

class Person(Entity):
has_field('name', Unicode)
has_many(
'assignments',
of_kind='Assignment',
inverse='person'
)

@property
def projects(self):
return (a.project for a in self.assignments)

class Project(Entity):
has_field('title', Unicode)
has_many(
'assignments',
of_kind='Assignment',
inverse='project'
)

class Assignment(Entity):
has_field('start_date', DateTime)
belongs_to(
'person',
of_kind='Person',
inverse='assignments'
)
belongs_to(
'project',
of_kind='Project',
inverse='assignments'
)

if __name__ == '__main__':
metadata.connect('sqlite:///')
metadata.create_all()

jon = Person(name='Jonathan')
daniel = Person(name='Daniel')
elix = Project(title='Elixir')
a1 = Assignment(
person=jon,
project=elix,
start_date=datetime.now()
)
a2 = Assignment(
person=daniel,
project=elix,
start_date=datetime.now()
)

objectstore.flush(); objectstore.clear()

p1 = Person.get(1)
for project in p1.projects:
print project.title


You could make the "projects" property on Person writable as well, if
you did a little extra work. I am planning on working on `has_many`
with a `through` keyword argument at some point in the future to
automatically create the properties, but haven't gotten around to it
yet (and might not anytime soon, depending on my schedule).

--
Jonathan LaCour
http://cleverdevil.org

nerkles

unread,
Aug 17, 2007, 11:08:43 AM8/17/07
to SQLElixir

Currently, I do it with an AssociationProxy. I needed to relate people
to their practice areas, sorted by whether it's their primary one,
etc.

from sqlalchemy.ext.associationproxy import AssociationProxy
from elixir import *

class Person(Entity):
has_field('name', Unicode)

has_many('pa_assoc', of_kind='PAPersonAssoc', inverse='person',
order_by='primacy', lazy=True)
practice_areas = AssociationProxy('pa_assoc', 'pa')

class PracticeArea(Entity):
has_field('name', Unicode)
has_many('pa_assoc', of_kind='PAPersonAssoc', inverse='pa',
order_by='primacy', lazy=True)
people = AssociationProxy('pa_assoc', 'person')

class PAPersonAssoc(Entity):
belongs_to('person', of_kind='Person', ondelete='cascade',
lazy=False)
belongs_to('pa', of_kind='PracticeArea', ondelete='cascade',
lazy=False)
has_field('primacy', Integer)

then you can access things like:
some_person.practice_areas[0]
some_practice_area.people[2]
etc.

The end result is pretty much the same as Jonathan's... not sure if
performance differs. Admittedly mine has more code and departs into
SQLAlchemy territory a little...

HTH...


Gaetan de Menten

unread,
Aug 20, 2007, 5:46:23 AM8/20/07
to sqle...@googlegroups.com
Association proxy is the way to go. And it seems like Jonathan
realized that before I had a chance to tell him :).

--
Gaëtan de Menten
http://openhex.org

Reply all
Reply to author
Forward
0 new messages