Two-to-Many Mapping between Models in Django ORM

15 views
Skip to first unread message

Rich Lewis

unread,
Jul 30, 2015, 11:10:56 AM7/30/15
to Django users
Dear All,

I'm new to the Django ORM, and quite new to ORMs in general.  I have two models (lets call them A and B) between which I have an interesting mapping.  There are precisely 2 B instances associated with each A instance.  Each A instance can have many B instances.  The order of Bs are important for As.

I want to do something like this:

class A(models.Model):
  b_1 = models.ForeignKey(B)
  b_2 = models.ForeignKey(B)

class B(models.Model):
  pass

Such that i can do:

>>> b1, b2, b3 = B(), B(), B()
>>> a1, a2 = A(b_1=b1, b_2=b2), A(b_1=b2, b_2=b3)
>>> b2.as
[<A ... >, <A ... >] #(order doesn't matter)

I expect I could eventually do something a bit hacky that would work, but what would be the best way to handle this?

Thanks in advance,

Richard

monoBOT

unread,
Jul 30, 2015, 11:21:37 AM7/30/15
to django...@googlegroups.com

2015-07-30 16:08 GMT+01:00 Rich Lewis <rich....@gmx.co.uk>:
There are precisely 2 B instances associated with each A instance.  Each A instance can have many B instances

Isnt that a contradiction?



--
monoBOT
Visite mi sitio(Visit my site): monobotsoft.es/blog/

Tom Evans

unread,
Jul 30, 2015, 12:15:40 PM7/30/15
to django...@googlegroups.com
On Thu, Jul 30, 2015 at 4:08 PM, Rich Lewis <rich....@gmx.co.uk> wrote:
> Dear All,
>
> I'm new to the Django ORM, and quite new to ORMs in general. I have two
> models (lets call them A and B) between which I have an interesting mapping.
> There are precisely 2 B instances associated with each A instance. Each A
> instance can have many B instances. The order of Bs are important for As.
>
> I want to do something like this:
>
> class A(models.Model):
> b_1 = models.ForeignKey(B)
> b_2 = models.ForeignKey(B)

This would fail here, when you have more than one foreign key to the
same model, you must supply a related_name argument on one of them,
which is used for the inverse relation on the related object. Which
leads us in to...

>
> class B(models.Model):
> pass
>
> Such that i can do:
>
>>>> b1, b2, b3 = B(), B(), B()
>>>> a1, a2 = A(b_1=b1, b_2=b2), A(b_1=b2, b_2=b3)
>>>> b2.as
> [<A ... >, <A ... >] #(order doesn't matter)

Typically, B instances would have an attribute named 'a_set' (the
lower case model name of the model it is related to, with "_set"
appended). When you have multiple relationships with the same model,
as I mentioned you must supply your own related_name arguments. In
which case, with the models you mentioned, you could then do something
like this:

>>> b2.a1_set.all() | b2.a2_set.all()
> [<A ..>, <A ..>]

>
> I expect I could eventually do something a bit hacky that would work, but
> what would be the best way to handle this?

I would say the above is the hacky way. You could have the same B
assigned to b_1 and b_2 and would have duplicates in the set, and no
way to specify DB constraints to limit it.

Given that you anticipate being able to retrieve all the A's for a
particular B, regardless of how they are related, I would model it as
a M2M with a through table holding any additional information about
the relationship, using the through table to add DB level constraints.

Cheers

Tom

Rich Lewis

unread,
Jul 30, 2015, 1:36:10 PM7/30/15
to Django users, monobo...@gmail.com
Oops sorry I meant every B instance can have multiple A instances.  Sorry!

Rich Lewis

unread,
Jul 30, 2015, 1:41:35 PM7/30/15
to Django users, teva...@googlemail.com
Hi Tom,

That was approximately what I was planning to do, I shall do some experimenting to see if I can do any more.  I was just wondering if there was a clever feature for this sort of thing, as ORMs seem pretty magic already!

Thanks,
Rich
Reply all
Reply to author
Forward
0 new messages