Thursday, July 30, 2015

Re: Two-to-Many Mapping between Models in Django ORM

On Thu, Jul 30, 2015 at 4:08 PM, Rich Lewis <rich.lewis@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

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAFHbX1%2B7-KieRLGT_hG-UDC6zeyg%2Bb8d%3D7XtEK4EEM8nFvzFng%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment