OneToManyField?

410 views
Skip to first unread message

Jonas Obrist

unread,
Jul 21, 2009, 10:12:32 AM7/21/09
to django-d...@googlegroups.com
In the documentation I see that there are Many-To-One Fields,
Many-To-Many Fields and One-To-One Fields. What about a One-To-Many
Field? You might now say that this is completely pointless since a
Many-To-One Field reversed is basically what I want. But I'd say that in
some cases it makes more sense to define a One-To-Many Field (because it
makes more sense to do it in Model A instead of Model B or whatever).
One of the reasons I would like to see this is that as it is now you
cannot directly edit reversed-relations through the admin page. You
always have to go 'forward'. With a One-To-Many Field the user could
choose in which Model he would like to edit the relationship on top on
having the possibility to keep his code more readable because of the
choice of Model where the relation is defined.

Related to this is that I'd say it would be favorable if reversed
relationships could be edited through the admin page by default.

Russell Keith-Magee

unread,
Jul 21, 2009, 11:42:12 AM7/21/09
to django-d...@googlegroups.com
On Tue, Jul 21, 2009 at 10:12 PM, Jonas Obrist<Ojii...@gmail.com> wrote:
>
> In the documentation I see that there are Many-To-One Fields,
> Many-To-Many Fields and One-To-One Fields. What about a One-To-Many
> Field? You might now say that this is completely pointless since a
> Many-To-One Field reversed is basically what I want. But I'd say that in
> some cases it makes more sense to define a One-To-Many Field (because it
> makes more sense to do it in Model A instead of Model B or whatever).

While I can see the reason why this is appealing from a data modeling
perspective, a quick look at the underlying mechanics quickly reveals
the reason why this hasn't been implemented.

If a model A has a foreign key on model B, then the table for A
requires a field to track the relation. However, if model B has a
"many to one" on A.... table A requires a field.

This makes the process of rolling out new models could lead to some
surprising situations. For example, with the current suite of relation
fields, you can always add a new model, run syncdb, and know that your
tables will be correct. However, this won't be the case if you allow
ManyToOne fields - you need to have the additional constraint that the
model to which you are linking hasn't been created yet.

In short, something that is a relatively simple from a data modeling
perspective has the potential to open all sorts of SQL management
problems.

Of course, this sort of thing would be much easier to handle if there
was a baked in schema evolution framework - but we don't have one of
those.... yet :-)

> Related to this is that I'd say it would be favorable if reversed
> relationships could be edited through the admin page by default.

This is a separate issue, but one that is more likely to get support -
although the real fix is to correct the underlying forms handling to
allow for the reverse relationships, not to fix admin specifically.

Yours,
Russ Magee %-)

dan

unread,
Jul 22, 2009, 4:05:56 AM7/22/09
to Django developers
>
> If a model A has a foreign key on model B, then the table for A
> requires a field to track the relation. However, if model B has a
> "many to one" on A.... table A requires a field.
>

sorry, can you clarify that for me? - specifically: "model A has a
foreign key on model B" - which direction do you mean exactly?

or let me try to put it differently: let's say that our model has two
domain classes: Parent and Child. (Parent can have many Children.)

Taking this model, and rewriting what you said: "If Parent has a
foreign key on Child, then the table for Parent requires a field to
track the relation. However, if Child has a "many-to-one" on
Parent... Parent requires a field."

Isn't that saying the same thing twice (and both times wrong)? If
Parent has a foreign key on Child, then the foreign key field is on
Child, right? And, if Child has a "many-to-one" on Parent, then,
again, Child has the foreign key field.

Or did I just think backwards when reading your post? ;)

I think what the original question is asking is, can the definition of
Parent have a "one-to-many" which points to Child? At the database
level there would be no difference: Child would still have the foreign
key field.

- dan

p.s. I don't mean to comment about where fixes should be made (in
Admin or in Forms, etc). Just trying to clarify the question.


Waylan Limberg

unread,
Jul 22, 2009, 9:00:28 AM7/22/09
to django-d...@googlegroups.com
On Wed, Jul 22, 2009 at 4:05 AM, dan<danst...@gmail.com> wrote:
>
[snip]

>
> I think what the original question is asking is, can the definition of
> Parent have a "one-to-many" which points to Child?  At the database
> level there would be no difference: Child would still have the foreign
> key field.
>
Right, and what Russ is saying is that the way models are currently
loaded that would break unless you could absolutely guarantee that
Parent always loaded before Child (or is it the other way?). As there
is currently no way to make that guarantee, Django will not support
the option at all. However, if, at some point in the future the
ability to make that guarantee becomes available, then they will
reconsider this feature. Until then, the way to address this is by
improving Forms.

--
----
\X/ /-\ `/ |_ /-\ |\|
Waylan Limberg

Russell Keith-Magee

unread,
Jul 22, 2009, 10:56:47 AM7/22/09
to django-d...@googlegroups.com
On Wed, Jul 22, 2009 at 4:05 PM, dan<danst...@gmail.com> wrote:
>
>>
>> If a model A has a foreign key on model B, then the table for A
>> requires a field to track the relation. However, if model B has a
>> "many to one" on A.... table A requires a field.
>
> sorry, can you clarify that for me? - specifically: "model A has a
> foreign key on model B" - which direction do you mean exactly?
...

> I think what the original question is asking is, can the definition of
> Parent have a "one-to-many" which points to Child?  At the database
> level there would be no difference: Child would still have the foreign
> key field.

You are absolutely correct that the databases would be identical.
However, this misses my point.

The critical difference is that under option 1, all the information
required to create the table for 'parent'. is contained on the Parent
model, and all the information required to create the table for
'child' is contained on the Child model. This means that as long as
you are able to import the model (i.e. there are no FK references to
models that haven't been defined), you can synchronize each model and
know that you have all the information that you require in order to
complete the synchronization accurately.

Under option 2, some of the information required for the child table
is contained on the Parent model. Therefore, you can't know for
certain if synchronization will be completed, because correctly
synchronizing Parent requires that the child either (a) hasn't been
synchronized, or (b) can be modified to add the new required column.

Why does this matter? This is entirely an issue of the complexity of
the synchronization process. Consider one of the most likely use
cases: writing a pluggable Django application that tracks the home
address of a contrib.auth.User.

I start with my project, and I add contrib.auth to INSTALLED_APPS. I
synchronize the database and set up admin, media etc.

Now, I want to add my pluggable "postal" application. This postal app
contains Address model:

class Address(Model):
street = CharField()
city = CharField()
zipcode = CharField()
users = ManyToOne(User)

However, I wouldn't be able to easily add my "postal" pluggable
application to INSTALLED_APPS. The auth.User table already exists, so
it isn't a simple task to add the extra 'address_id' column that the
Address model requires.

Resolving this sort of problem requires the ability to perform
database schema migrations as part of the synchronization process.
Until Django has a migration tool baked in, it isn't really feasible
to have a ManyToOne field.

Even then - we would need to be able to ensure that migrations would
always be able to succeed. For example, what if address was a required
field, and I have existing Users? What value for address_id to those
users receive as part of the migration?

I can sympathize with the intention of the ManyToOne idea. However,
adding this apparently simple idea opens up a Pandora's box of
problems. Forcing 1-N relations to be defined by ForeignKey (and not
by the reverse relation) avoids all these problems.

Yours,
Russ Magee %-)

Reply all
Reply to author
Forward
0 new messages