Adding a OneToMany Relationship to Django

665 views
Skip to first unread message

Amir Rachum

unread,
Jun 15, 2013, 11:11:53 AM6/15/13
to django-d...@googlegroups.com
Hi there,

I'm not sure if this feature was discussed before (I've seen some mentions of it when searching this group, but nothing definitive).
I have written a blog post regarding the reasons (and the suggested syntax) to use this relationship, and would love some feedback


Thanks,
Amir Rachum

Luke Sneeringer

unread,
Jun 15, 2013, 12:05:02 PM6/15/13
to django-d...@googlegroups.com
It seems to me that "there should be one--and preferably only one--way to do it." This would entail having two ways.

Sometimes that makes sense if they're distinct enough things conceptually, but personally I don't see that case.

Best Regards,
Luke Sneeringer

Sent from my iPhone. Forgive us our typos as we forgive those who typo against us.
--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Tomas Ehrlich

unread,
Jun 15, 2013, 12:06:05 PM6/15/13
to django-d...@googlegroups.com
Hello Amir,
you've mentioned only definiton of model. Yes, it looks interesting and
definitely more readable. But definition of model is just the begining.

At database level, these models would be represented in the same way.
(No difference)

Working with models would be similar or even the same as it's now:
``member.group = band`` or ``band.members.add(member)``
Again, I don't see any difference.

There would be probably some constraint when you try delete member of
band which doesn't have any other members. Now, that could be
implemented using pre_delete/post_delete signals.


It looks for me that the only difference is in readability of
models.py. What am I missing?


Cheers,
Tomas Ehrlich




Dne Sat, 15 Jun 2013 08:11:53 -0700 (PDT)
Amir Rachum <nur...@gmail.com> napsal(a):

Carl Meyer

unread,
Jun 15, 2013, 1:04:36 PM6/15/13
to django-d...@googlegroups.com
Hi Amir,

On Jun 15, 2013, at 9:11 AM, Amir Rachum <nur...@gmail.com> wrote:
The strongest reason not to do this is that it breaks the correspondence between model fields and database columns. If you added a new OneToMany field on Band pointing to Musician, suddenly the (unmodified) Musician model's db table would require a schema migration, while the Band table would remain unchanged. (Yes, ManyToManyField already sort of breaks this correspondence, but only in that it causes a new table to be created in the same app where you added the field. It never requires a schema migration for an untouched model class, possibly in a different app, which is much worse.)

I think this downside alone is enough to kill the proposal for Django core, especially considering the rationale in favor isn't that strong; it's just a new way to spell the exact equivalent of a ForeignKey.

That said, I'm pretty sure you could code this up outside of core, if you'd like to experiment with it.

Carl

Curtis Maloney

unread,
Jul 10, 2013, 4:20:07 AM7/10/13
to django-d...@googlegroups.com
I've seen enough people in #django suffering because they need a FKey on a table they simply can't alter -- be it because it's in a 3rd party app, or simply a table their DBA won't permit them to alter, or what have you.

In the end they wind up having to create the equivalent of a m2m through table, but with one side being a 1to1.

ISTM that the sugar to make this behave wouldn't be much greater than that used for MTI, but I say that having not delved yet, so... what would I know? :)

--
Curtis

Loic Bistuer

unread,
Jul 10, 2013, 4:59:07 AM7/10/13
to django-d...@googlegroups.com
I totally agree that we can't have a field on one model that modifies the underlying table of another model, especially with migrations in mind.

That said, I see value in a OneToManyField backed by a M2M with a unique constraint on one side. This is particularly useful when you don't want to modify a third-party app.

Of course it can be done manually, but then the API isn't that great.

Generalizing (documenting) swappable models could be another answer to this issue and yet it would probably be overkill for this purpose.

--
Loic

Russell Keith-Magee

unread,
Jul 10, 2013, 7:33:51 PM7/10/13
to django-d...@googlegroups.com
On Wed, Jul 10, 2013 at 4:20 PM, Curtis Maloney <cur...@acommoncreative.com> wrote:
I've seen enough people in #django suffering because they need a FKey on a table they simply can't alter -- be it because it's in a 3rd party app, or simply a table their DBA won't permit them to alter, or what have you.

In the end they wind up having to create the equivalent of a m2m through table, but with one side being a 1to1.

ISTM that the sugar to make this behave wouldn't be much greater than that used for MTI, but I say that having not delved yet, so... what would I know? :)

This is a use case I've seen many times in the past -- most commonly with the User model, but with others as well. To that end, I have a certain sympathy for the request.

I'm not sure I completely agree with Carl that is breaks correspondence -- after all, m2m fields don't correlate to a field, either. However, in the absence of a built-in migrations framework, I suspect a O2M field would be a pretty efficient foot-gun for newcomers.

That said - I agree that it should be possible to implement this external to core. There's a certain amount of "here be dragons" in the django.db.models.fields.related code, but it should be relatively straightforward to implement the reverse of a ForeignKey. If someone is interested in this, I'd rather see it proven as an external tool before we add it to core.

Yours,
Russ Magee %-)

Carl Meyer

unread,
Jul 10, 2013, 7:40:30 PM7/10/13
to django-d...@googlegroups.com
Hi Russ,

On 07/10/2013 05:33 PM, Russell Keith-Magee wrote:
> On Wed, Jul 10, 2013 at 4:20 PM, Curtis Maloney
> <cur...@acommoncreative.com <mailto:cur...@acommoncreative.com>> wrote:
>
> I've seen enough people in #django suffering because they need a
> FKey on a table they simply can't alter -- be it because it's in a
> 3rd party app, or simply a table their DBA won't permit them to
> alter, or what have you.
>
> In the end they wind up having to create the equivalent of a m2m
> through table, but with one side being a 1to1.
>
> ISTM that the sugar to make this behave wouldn't be much greater
> than that used for MTI, but I say that having not delved yet, so...
> what would I know? :)
>
>
> This is a use case I've seen many times in the past -- most commonly
> with the User model, but with others as well. To that end, I have a
> certain sympathy for the request.
>
> I'm not sure I completely agree with Carl that is breaks correspondence
> -- after all, m2m fields don't correlate to a field, either. However, in
> the absence of a built-in migrations framework, I suspect a O2M field
> would be a pretty efficient foot-gun for newcomers.

I mentioned the m2m case in my email. The more basic invariant (that is
currently respected by all built-in fields) is "when you put a field on
a model, it creates or changes db tables in that model's app, not some
other app."

What's being requested here is essentially an ORM variant of
monkeypatching third-party apps. While I accept that monkeypatching
third-party code is sometimes pragmatically the best of bad options, I
don't think it's a technique that we should be blessing with a built-in
first-class field type.

Carl

> That said - I agree that it should be possible to implement this
> external to core. There's a certain amount of "here be dragons" in the
> django.db.models.fields.related code, but it should be relatively
> straightforward to implement the reverse of a ForeignKey. If someone is
> interested in this, I'd rather see it proven as an external tool before
> we add it to core.

For sure.

Carl

Carl Meyer

unread,
Jul 10, 2013, 8:13:05 PM7/10/13
to django-d...@googlegroups.com
On 07/10/2013 05:40 PM, Carl Meyer wrote:
>> I'm not sure I completely agree with Carl that is breaks correspondence
>> -- after all, m2m fields don't correlate to a field, either. However, in
>> the absence of a built-in migrations framework, I suspect a O2M field
>> would be a pretty efficient foot-gun for newcomers.
>
> I mentioned the m2m case in my email. The more basic invariant (that is
> currently respected by all built-in fields) is "when you put a field on
> a model, it creates or changes db tables in that model's app, not some
> other app."
>
> What's being requested here is essentially an ORM variant of
> monkeypatching third-party apps. While I accept that monkeypatching
> third-party code is sometimes pragmatically the best of bad options, I
> don't think it's a technique that we should be blessing with a built-in
> first-class field type.

Er, never mind all this. I missed that the latest version of the
proposal is for an M2M-like table with a unique constraint on one side
of it, rather than adding a real FKey to the remote table. In that case,
this "monkeypatching" objection doesn't apply.

It's still a slightly unnatural (and less efficient) way to model the
data, even if useful in some cases; not sure it meets the barrier for
inclusion in core, but we can see how it works out externally.

Carl

Loic Bistuer

unread,
Jul 11, 2013, 1:22:10 AM7/11/13
to django-d...@googlegroups.com
It's less efficient because of the extra table but that's pretty much the only option when you need a FK on a model that you can't edit. GFK are not exactly efficient either, yet most will agree that it's sometime the best option to a given problem.

I agree that the distinction between FK and O2M might be a little confusing to newcomers but I think it can be addressed with sufficient documentation.

I would work on a patch if we have an accepted ticket.

-- 
Loic
Reply all
Reply to author
Forward
0 new messages