I thought I'd post my solution in case anyone faces a similar situation.
Problem: I am using an intermediate model (R) to represent a
relationship between models Location and Thread. Given an instance of
Location, say x, I want the property x.threads to return a QuerySet
containing all of the related thread instances. This requires spanning
the R relationship, since I don't want instances of R. This is nice
because it is convenient, it hides implementation, and is a lazy
queryset.
Solution: I wrote a function that writes a ".extra()" query. I
couldn't find an easier way. Anyway its the first time I used .extra
and ._meta, so I'm not sure how reliable it is. I would appreciate any
feedback matter :) Its not entirely general yet...
def span_table(sourceField, targetField, relnModel, sourceModel, targetModel,
moreTables=[], moreWhere=[], moreParams=[]):
# moreTables, moreWhere, and moreParams let you restrict
# on fields stored in the intermediate table
relnTable = relnModel._meta.db_table
targetTable = targetModel._meta.db_table
targetPkColumn = targetModel._meta.pk.column
sourcePkAttr = sourceModel._meta.pk.attname
tables = [ relnTable ] + moreTables
where = [
'%s.%s_id = %s' % (relnTable, sourceField, '%s'),
'%s.%s_id = %s.%s' % (relnTable, targetField, targetTable,
targetPkColumn)
] + moreWhere
def f(sourceObject, **kw):
params = [ getattr( sourceObject, sourcePkAttr ) ] + moreParams
# assumes the manager is objects...
return targetModel.objects.filter(**kw).extra(
tables=tables, where=where, params=params )
return f
class Thread(models.model):
pass
class Location(models.model):
pass
class LocationThread(models.model):
thread = models.ForeignKey( Thread )
location = models.ForeignKey( Location)
# using the function
Location.threads = property( span_table('location', 'thread',
LocationThread, Location, Thread) )
so now myLocation.threads returns a query set
Best,
- Steve
On 10/16/06, Steve Wedig <[EMAIL PROTECTED]> wrote:
> Alrighty, I've pulled out the relationships into separate separate
> models, as shown below. This correctly represents the information.
> However, I would like to work with the sets of related threads
> directly, rather than always traversing the intermediate models.
>
> I'm not sure how to write the functions where the ???'s appear below.
> I'd like to return a lazy QuerySet of threads (so basically pretending
> the threads are directly related). I would appreciate any advice on
> this matter...
>
> class Thread(models.model): # threads don't care where they are used
>
> class Location(models.model):
> def thread_set(self):
> ???
> thread_set = property(thread_set)
>
> class LocationThread(models.model): # m-n relationship
> thread = models.ForeignKey( Thread )
> location = models.ForeignKey( Location)
>
> class Group(models.model):
> def thread_set(self):
> ???
> thread_set = property(thread_set)
>
> class GroupThread(models.model): # m-1 relationship
> thread = models.OneToOneField( Thread )
> location = models.ForeignKey( Location)
>
> Thanks,
> Steve
>
> On 10/16/06, Malcolm Tredinnick <[EMAIL PROTECTED]> wrote:
> >
> > On Mon, 2006-10-16 at 02:44 -0700, Steve Wedig wrote:
> > > I have a thread model that I would like to reuse in multiple places.
> > > So a thread should have no knowledge of where it is contained.
> > >
> > > I also have a group model and a location model. I would like to have
> > > multple threads in a group (1-n reln between group and thread). I
> > > would also like threads to appear at _multiple_ locations (so a m-n
> > > reln between location and thread).
> > >
> > > I am wondering, what is the best way to accomplish this in django? I
> > > am reasonably familiar with the generic relation mechanism, however
> > > that appears to only work for 1-n relationships. Plus I don't want to
> > > a thread to worry about where/how it is used/contained.
> >
> > A many-to-many relation is identical to two one-to-many relations put
> > back-to-back. Think about how a many-to-many relation is implemented at
> > the table level (whether by Django or in any database setup): you have a
> > table in the middle that contains pairs of entries, one from each end of
> > the many-to-many relation.
> >
> > So I would think you could create a many-to-many generic relation by
> > having an intermediate model that is 1-n to both the thread and location
> > models. All the intermediate model does is handle the connection. Note
> > that I haven't actually worked out the details, but I can't think of any
> > insurmountable problem. If you get stuck implementing this, sing out and
> > we should be able to help.
> >
> > Regards,
> > Malcolm
> >
> >
> >
> > > >
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-users
-~----------~----~----~----~------~----~------~--~---