Idea for dealing with circular ForeignKey references

29 views
Skip to first unread message

Robin Munn

unread,
Jul 30, 2005, 1:11:49 AM7/30/05
to django-d...@googlegroups.com
I just wrote a nice long comment in
http://code.djangoproject.com/ticket/167 about how tricky it is to
deal with circular ForeignKey references, and how I think we should
put that feature off until after the 1.0 release, at the /very/ least.
But then I started thinking: when you declare a ForeignKey
relationship in a Django model, it doesn't just affect the database.
It also creates some handy lookup functions that do automatic joins
for you, and lets you do get_related=True during lookups, all kinds of
neat features. If I was writing a data model that wanted to use
circular ForeignKey references, I'd want those handy functions, but
I'd want to avoid the hassle of having the database enfore data
integrity for me, because circular data-integrity references are a
pain to work with sometimes. (See my comment for examples). So why not
have an extra optional kwarg "enforce" which defaults to True? It
would trigger whether FOREIGN KEY constraints were created in the
table. Having a ForeignKey(enforce=False) would mean that all the
handy lookup functions would get created, but the database wouldn't
use FOREIGN KEY constraints to enforce them.

This would bring us very very close to allowing the following code to work:

class Person(meta.Model):
fields = (
meta.StringField('name', maxlength=20),
# ...
meta.ForeignKey('Address', enforce=False),
)

class Address(meta.Model):
fields = (
meta.StringField('street', maxlength=20),
# ...
meta.ForeignKey(Person),
)

Of course, we'd still need to be able to handle strings as ForeignKey
parameters, which is a ways off yet from becoming reality; but I think
just having this much would answer 90% of the feature requests where
someone asks for circular ForeignKeys. 90% of the time, IMHO, they
don't *really* want circular ForeignKeys and all the database hassles
that come with them, they just want easy convenience methods for doing
joins and the like. And I see no reason why we shouldn't give it to
them.

--
Robin Munn
Robin...@gmail.com
GPG key 0xD6497014

Martin Maney

unread,
Aug 3, 2005, 3:48:51 PM8/3/05
to Django developers
An FK cycle, at least as described in the ticket, is probably better
modeled as a many-to-many relation. In this case the realtionship
would carry (at least) two binary flags for "owns" and "lives at".
Surely that will have to be extended with a "sends mail to" as soon as
the department of Homeland Fake-security hears of its existence!

The whole business with enforce=False is a hack, and not a good one
IMO. What you really need for this sort of thing is transactions (and
then we may need a defer_enforcement option not only for FKs but for
any constraint the database itself enforces; also note that the
explicit m2m avoids that because the reflexive links don't have to be
inserted at the same time the referenced rows are being created).
Without that you can have only an illusion of data integrity, even
though it works most of the time.

Reply all
Reply to author
Forward
0 new messages