Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Ticket #7539 (ON DELETE support) in Django 1.2?

25 views
Skip to first unread message

Michael Glassford

unread,
Aug 12, 2009, 12:04:18 PM8/12/09
to django-d...@googlegroups.com
Previously accidentally posted to the Django users group instead of
here. Sorry!



http://code.djangoproject.com/ticket/7539 suggests a way to add On
Delete and On Update support to Django foreign key fields, and includes
a patch that implements the suggestions. At the time I submitted it,
getting Django 1.1 out the door prevented it from being seriously
considered, but now that 1.2 is in the planning stages, how about it?

The ticket actually suggests several changes:

1) Adding an on_delete parameter to ForeignKey definitions and allowing
it to specify CASCADE, SET_NULL, or RESTRICT behavior.

2) Modifying Django's built-in behavior, which currently always cascades
deletes, to handle the new SET_NULL and RESTRICT behaviors. Django still
defaults to CASCADE behavior for foreign keys that don't specify an
on_delete parameter.

3) Allowing settings files to change the default on delete behavior from
CASCADE to one of the other options for foreign keys that don't specify
an on_delete parameter.

4) Allowing settings files to specify that the on_delete behavior should
be handled by the database backend rather than by Django, and changing
the SQL generated by Django to contain appropriate ON DELETE clauses.

5) Adding an on_update parameter to ForeignKey definitions. Unlike the
on_delete parameter, the patch doesn't implement built-in emulation of
on_update: on_update clauses are only handled by the database backend.


I believe that items 1-3 are in a form that is usable with little
modification, and would like to suggest that at least this much be added
to 1.2.

Items 4 and 5 would need more work to support more back ends before it
makes sense to include them.

It might also be nice to have an implementation of item 5 that doesn't
depend on the db backend, although this might require a significant
amount of work.




Russell Keith-Magee

unread,
Aug 13, 2009, 8:30:55 AM8/13/09
to django-d...@googlegroups.com
On Thu, Aug 13, 2009 at 12:04 AM, Michael Glassford<glass...@gmail.com> wrote:
>
> http://code.djangoproject.com/ticket/7539 suggests a way to add On
> Delete and On Update support to Django foreign key fields, and includes
> a patch that implements the suggestions. At the time I submitted it,
> getting Django 1.1 out the door prevented it from being seriously
> considered, but now that 1.2 is in the planning stages, how about it?
>
> The ticket actually suggests several changes:
>
> 1) Adding an on_delete parameter to ForeignKey definitions and allowing
> it to specify CASCADE, SET_NULL, or RESTRICT behavior.
>
> 2) Modifying Django's built-in behavior, which currently always cascades
> deletes, to handle the new SET_NULL and RESTRICT behaviors. Django still
> defaults to CASCADE behavior for foreign keys that don't specify an
> on_delete parameter.
>
> 3) Allowing settings files to change the default on delete behavior from
> CASCADE to one of the other options for foreign keys that don't specify
> an on_delete parameter.

I'm not convinced that this is a good idea. Explicit is better than
implicit. Imagine the case where I write an application with foreign
keys that assume CASCADE, since that is the system default; then you
deploy in an project where RESTRICT is the default. Hilarity ensues.

> 4) Allowing settings files to specify that the on_delete behavior should
> be handled by the database backend rather than by Django, and changing
> the SQL generated by Django to contain appropriate ON DELETE clauses.
>
> 5) Adding an on_update parameter to ForeignKey definitions. Unlike the
> on_delete parameter, the patch doesn't implement built-in emulation of
> on_update: on_update clauses are only handled by the database backend.
>
>
> I believe that items 1-3 are in a form that is usable with little
> modification, and would like to suggest that at least this much be added
> to 1.2.
>
> Items 4 and 5 would need more work to support more back ends before it
> makes sense to include them.
>
> It might also be nice to have an implementation of item 5 that doesn't
> depend on the db backend, although this might require a significant
> amount of work.

I'm all in favor of improving the delete cascading support in Django.

I have some concerns, however.

Firstly: are you volunteering to do the work? These would be
interesting additions to Django, but the magic fairy isn't going to
write these :-)

Secondly: I'm sensitive to the extent that 'on delete cascade' et al
are phrased in SQL specific terms. I fully acknowledge the use case -
what happens to a FK when the object it points to is deleted - but I
want to make sure that we phrase it in a way that makes sense with
non-SQL backends. Have you had any thoughts about this?

Thirdly: Cross database support - especially when you get to
SQL-native implementations - will be a big issue here. Have you done
(or are you prepared to do) a survey of the various Django supported
backends to find the status of support for various ON DELETE/ON UPDATE
options?

Yours
Russ Magee %-)

Michael Glassford

unread,
Aug 13, 2009, 12:06:35 PM8/13/09
to public-django-developer...@hugh.gmane.org

Russell Keith-Magee wrote:


> On Thu, Aug 13, 2009 at 12:04 AM, Michael Glassford<glassfordm-Re5JQ...@public.gmane.org> wrote:
>> http://code.djangoproject.com/ticket/7539 suggests a way to add On
>> Delete and On Update support to Django foreign key fields, and includes
>> a patch that implements the suggestions. At the time I submitted it,
>> getting Django 1.1 out the door prevented it from being seriously
>> considered, but now that 1.2 is in the planning stages, how about it?
>>
>> The ticket actually suggests several changes:
>>
>> 1) Adding an on_delete parameter to ForeignKey definitions and allowing
>> it to specify CASCADE, SET_NULL, or RESTRICT behavior.
>>
>> 2) Modifying Django's built-in behavior, which currently always cascades
>> deletes, to handle the new SET_NULL and RESTRICT behaviors. Django still
>> defaults to CASCADE behavior for foreign keys that don't specify an
>> on_delete parameter.
>>
>> 3) Allowing settings files to change the default on delete behavior from
>> CASCADE to one of the other options for foreign keys that don't specify
>> an on_delete parameter.
>
> I'm not convinced that this is a good idea. Explicit is better than
> implicit. Imagine the case where I write an application with foreign
> keys that assume CASCADE, since that is the system default; then you
> deploy in an project where RESTRICT is the default. Hilarity ensues.

True enough.

When you say "explicit is better...", are you recommending requiring all
foreign keys to specify an on_delete option, or only those that don't
want to CASCADE (I assume the latter)? There are still people who are
surprised by the CASCADE default behavior, which is why I suggested the
setting in the first place.

>> 4) Allowing settings files to specify that the on_delete behavior should
>> be handled by the database backend rather than by Django, and changing
>> the SQL generated by Django to contain appropriate ON DELETE clauses.
>>
>> 5) Adding an on_update parameter to ForeignKey definitions. Unlike the
>> on_delete parameter, the patch doesn't implement built-in emulation of
>> on_update: on_update clauses are only handled by the database backend.
>>
>>
>> I believe that items 1-3 are in a form that is usable with little
>> modification, and would like to suggest that at least this much be added
>> to 1.2.
>>
>> Items 4 and 5 would need more work to support more back ends before it
>> makes sense to include them.
>>
>> It might also be nice to have an implementation of item 5 that doesn't
>> depend on the db backend, although this might require a significant
>> amount of work.
>
> I'm all in favor of improving the delete cascading support in Django.
>
> I have some concerns, however.
>
> Firstly: are you volunteering to do the work? These would be
> interesting additions to Django, but the magic fairy isn't going to
> write these :-)

As far as I know, the work for items 1-3 is already done and in the
patch (though it may need to be updated). This is all I'm suggesting
adding to Django 1.2.

Item 4 is done for MySQL; I'm not really in a position to extend it to
other backends, which is why I'm not suggesting it for Django 1.2.

Item 5 (without the suggested addition of building ON UPDATE behavior
into Django itself) is also done for MySQL. Again, I'm not in a position
to extend it to other backends. I might be able to do the work to add
the ON UPDATE behavior to Django itself at some point, but probably not
for 1.2.

> Secondly: I'm sensitive to the extent that 'on delete cascade' et al
> are phrased in SQL specific terms. I fully acknowledge the use case -
> what happens to a FK when the object it points to is deleted - but I
> want to make sure that we phrase it in a way that makes sense with
> non-SQL backends. Have you had any thoughts about this?

I think the three options I included (CASCADE, RESTRICT, and SET_NULL)
make sense for non-SQL backends, although I'd be glad to rename them and
use non-SQL terminology. This is especially true since the terms don't
appear to mean exactly the same thing even across SQL implementations
(for instance, if I remember correctly, RESTRICT behaves differentlt in
MySQL and Oracle).

> Thirdly: Cross database support - especially when you get to
> SQL-native implementations - will be a big issue here. Have you done
> (or are you prepared to do) a survey of the various Django supported
> backends to find the status of support for various ON DELETE/ON UPDATE
> options?

I haven't done such a survey and probably I'm not the right person to do
so. However, I'm not sure it's necessary now, since I'm only suggesting
adding items 1-3 here, and since those items are implemented at a high
enough level in Django (i.e., at the same level where it currently
implements the default CASCADE behavior) that they should work
independently of the backend, unless there's something that I'm missing.

Mike

Russell Keith-Magee

unread,
Aug 13, 2009, 8:31:07 PM8/13/09
to django-d...@googlegroups.com
On Fri, Aug 14, 2009 at 12:06 AM, Michael Glassford<glass...@gmail.com> wrote:
>
> Russell Keith-Magee wrote:
>> On Thu, Aug 13, 2009 at 12:04 AM, Michael Glassford<glass...@gmail.com> wrote:
>>> http://code.djangoproject.com/ticket/7539 suggests a way to add On
>>> Delete and On Update support to Django foreign key fields, and includes
>>> a patch that implements the suggestions. At the time I submitted it,
>>> getting Django 1.1 out the door prevented it from being seriously
>>> considered, but now that 1.2 is in the planning stages, how about it?
>>>
>>> The ticket actually suggests several changes:
>>>
>>> 1) Adding an on_delete parameter to ForeignKey definitions and allowing
>>> it to specify CASCADE, SET_NULL, or RESTRICT behavior.
>>>
>>> 2) Modifying Django's built-in behavior, which currently always cascades
>>> deletes, to handle the new SET_NULL and RESTRICT behaviors. Django still
>>> defaults to CASCADE behavior for foreign keys that don't specify an
>>> on_delete parameter.
>>>
>>> 3) Allowing settings files to change the default on delete behavior from
>>> CASCADE to one of the other options for foreign keys that don't specify
>>> an on_delete parameter.
>>
>> I'm not convinced that this is a good idea. Explicit is better than
>> implicit. Imagine the case where I write an application with foreign
>> keys that assume CASCADE, since that is the system default; then you
>> deploy in an project where RESTRICT is the default. Hilarity ensues.
>
> True enough.
>
> When you say "explicit is better...", are you recommending requiring all
> foreign keys to specify an on_delete option, or only those that don't
> want to CASCADE (I assume the latter)?

The latter. All existing model definitions must continue to work the
same without modification. If we add an option, that option must
default to historical behavior.

> There are still people who are
> surprised by the CASCADE default behavior, which is why I suggested the
> setting in the first place.

Having CASCADE as a default may be surprising, but we're not in a
position to change that - it's the current default, so we're stuck
with it.

As indicated, adding a system wide setting has other consequences.
This is one of those situations where "just add a setting" makes the
problem worse, not better.

>>> 4) Allowing settings files to specify that the on_delete behavior should
>>> be handled by the database backend rather than by Django, and changing
>>> the SQL generated by Django to contain appropriate ON DELETE clauses.
>>>
>>> 5) Adding an on_update parameter to ForeignKey definitions. Unlike the
>>> on_delete parameter, the patch doesn't implement built-in emulation of
>>> on_update: on_update clauses are only handled by the database backend.
>>>
>>>
>>> I believe that items 1-3 are in a form that is usable with little
>>> modification, and would like to suggest that at least this much be added
>>> to 1.2.
>>>
>>> Items 4 and 5 would need more work to support more back ends before it
>>> makes sense to include them.
>>>
>>> It might also be nice to have an implementation of item 5 that doesn't
>>> depend on the db backend, although this might require a significant
>>> amount of work.
>>
>> I'm all in favor of improving the delete cascading support in Django.
>>
>> I have some concerns, however.
>>
>> Firstly: are you volunteering to do the work? These would be
>> interesting additions to Django, but the magic fairy isn't going to
>> write these :-)
>
> As far as I know, the work for items 1-3 is already done and in the
> patch (though it may need to be updated). This is all I'm suggesting
> adding to Django 1.2.

I have no problem with items 1-2. Item 3 probably isn't an option, as
I have indicated.

> Item 4 is done for MySQL; I'm not really in a position to extend it to
> other backends, which is why I'm not suggesting it for Django 1.2.
>
> Item 5 (without the suggested addition of building ON UPDATE behavior
> into Django itself) is also done for MySQL. Again, I'm not in a position
> to extend it to other backends. I might be able to do the work to add
> the ON UPDATE behavior to Django itself at some point, but probably not
> for 1.2.

Ok - there's no reason this can't be tackled in multiple stages.

>> Secondly: I'm sensitive to the extent that 'on delete cascade' et al
>> are phrased in SQL specific terms. I fully acknowledge the use case -
>> what happens to a FK when the object it points to is deleted - but I
>> want to make sure that we phrase it in a way that makes sense with
>> non-SQL backends. Have you had any thoughts about this?
>
> I think the three options I included (CASCADE, RESTRICT, and SET_NULL)
> make sense for non-SQL backends, although I'd be glad to rename them and
> use non-SQL terminology.

There are two aspects to consider - naming and functionality.

From a naming perspective, SET_NULL is clearly wrong. The slightly
inconsistent behavior of RESTRICT between databases suggests that it
might not be the best name - we don't want to carry any DBMS baggage
in the terms we adopt.

As for functionality: CASCADE is obviously ok. Your proposal misses
the SET DEFAULT and NO ACTION options. The difference between NO
ACTION and RESTRICT is a subtlety of SQL, so the omission makes sense.
However, SET DEFAULT makes sense, and could be quite useful.

~~~~~

I'm broadly in favour of this proposal. There are some details that
may need to be sorted out, but they're mostly porcelain, not plumbing
- the core of the feature proposal itself is well defined.

So, all that is left is to stick the ticket on the v1.2 Feature wiki
page so that it is considered when the time comes.

Also, keep working on the patch. I notice that the latest patch
doesn't contain any tests or documentation (although the earlier patch
contains tests) - both will be required before the feature lands.

Yours,
Russ Magee %-)

Michael Glassford

unread,
Aug 13, 2009, 9:16:48 PM8/13/09
to public-django-developer...@hugh.gmane.org

Russell Keith-Magee wrote:


> On Fri, Aug 14, 2009 at 12:06 AM, Michael Glassford<glassfordm-Re5JQ...@public.gmane.org> wrote:
>> Russell Keith-Magee wrote:

Right. I didn't actually state it, but I was assuming that, if any
change were made to require foreign keys to specify an on_delete option,
it would have to be something that could be turned on in the settings
file and would default to off. This wouldn't have the same problem that
you pointed out with the setting I specified in #3 above (wonky behavior
for models created with one value of the setting when run with the other
value of the setting).

>> There are still people who are
>> surprised by the CASCADE default behavior, which is why I suggested the
>> setting in the first place.
>
> Having CASCADE as a default may be surprising, but we're not in a
> position to change that - it's the current default, so we're stuck
> with it.

Unless it's a setting, as I said above. I'm not suggesting that there
should be such a setting, just saying that it could be done that way.

> As indicated, adding a system wide setting has other consequences.
> This is one of those situations where "just add a setting" makes the
> problem worse, not better.

I agree.

>>>> 4) Allowing settings files to specify that the on_delete behavior should
>>>> be handled by the database backend rather than by Django, and changing
>>>> the SQL generated by Django to contain appropriate ON DELETE clauses.
>>>>
>>>> 5) Adding an on_update parameter to ForeignKey definitions. Unlike the
>>>> on_delete parameter, the patch doesn't implement built-in emulation of
>>>> on_update: on_update clauses are only handled by the database backend.
>>>>
>>>>
>>>> I believe that items 1-3 are in a form that is usable with little
>>>> modification, and would like to suggest that at least this much be added
>>>> to 1.2.
>>>>
>>>> Items 4 and 5 would need more work to support more back ends before it
>>>> makes sense to include them.
>>>>
>>>> It might also be nice to have an implementation of item 5 that doesn't
>>>> depend on the db backend, although this might require a significant
>>>> amount of work.
>>> I'm all in favor of improving the delete cascading support in Django.
>>>
>>> I have some concerns, however.
>>>
>>> Firstly: are you volunteering to do the work? These would be
>>> interesting additions to Django, but the magic fairy isn't going to
>>> write these :-)
>> As far as I know, the work for items 1-3 is already done and in the
>> patch (though it may need to be updated). This is all I'm suggesting
>> adding to Django 1.2.
>
> I have no problem with items 1-2. Item 3 probably isn't an option, as
> I have indicated.

Right. I meant to say 1-2 instead of 1-3: you made it clear before that
item 3 is out, and I agree that it should be.

>> Item 4 is done for MySQL; I'm not really in a position to extend it to
>> other backends, which is why I'm not suggesting it for Django 1.2.
>>
>> Item 5 (without the suggested addition of building ON UPDATE behavior
>> into Django itself) is also done for MySQL. Again, I'm not in a position
>> to extend it to other backends. I might be able to do the work to add
>> the ON UPDATE behavior to Django itself at some point, but probably not
>> for 1.2.
>
> Ok - there's no reason this can't be tackled in multiple stages.
>
>>> Secondly: I'm sensitive to the extent that 'on delete cascade' et al
>>> are phrased in SQL specific terms. I fully acknowledge the use case -
>>> what happens to a FK when the object it points to is deleted - but I
>>> want to make sure that we phrase it in a way that makes sense with
>>> non-SQL backends. Have you had any thoughts about this?
>> I think the three options I included (CASCADE, RESTRICT, and SET_NULL)
>> make sense for non-SQL backends, although I'd be glad to rename them and
>> use non-SQL terminology.
>
> There are two aspects to consider - naming and functionality.
>
> From a naming perspective, SET_NULL is clearly wrong.

SET_NONE instead, then?

> The slightly
> inconsistent behavior of RESTRICT between databases suggests that it
> might not be the best name - we don't want to carry any DBMS baggage
> in the terms we adopt.

That's also what I was thinking.

> As for functionality: CASCADE is obviously ok. Your proposal misses
> the SET DEFAULT and NO ACTION options. The difference between NO
> ACTION and RESTRICT is a subtlety of SQL, so the omission makes sense.

That was my thinking when I left out NO ACTION.

> However, SET DEFAULT makes sense, and could be quite useful.

OK.

So how about these options with this naming:

CASCADE (or CASCADE_DELETE)
PREVENT (or PREVENT_DELETE) (prevents anything from being deleted)
SET_NONE
SET_DEFAULT

> ~~~~~
>
> I'm broadly in favour of this proposal. There are some details that
> may need to be sorted out, but they're mostly porcelain, not plumbing
> - the core of the feature proposal itself is well defined.
>
> So, all that is left is to stick the ticket on the v1.2 Feature wiki
> page so that it is considered when the time comes.

Should I do this?

> Also, keep working on the patch. I notice that the latest patch
> doesn't contain any tests or documentation (although the earlier patch
> contains tests) - both will be required before the feature lands.

Really, the tests are missing? That was an accidental omission, then--I
still have the tests running locally.

Once we agree on naming changes, I'll work up a patch that implements
only items 1-2, with the naming changes, including tests.

What's the best way to add documentation? Should it be a patch against
the existing docs?

Mike

Russell Keith-Magee

unread,
Aug 13, 2009, 10:09:35 PM8/13/09
to django-d...@googlegroups.com
On Fri, Aug 14, 2009 at 9:16 AM, Michael Glassford<glass...@gmail.com> wrote:
>
> Russell Keith-Magee wrote:
>>>> Secondly: I'm sensitive to the extent that 'on delete cascade' et al
>>>> are phrased in SQL specific terms. I fully acknowledge the use case -
>>>> what happens to a FK when the object it points to is deleted - but I
>>>> want to make sure that we phrase it in a way that makes sense with
>>>> non-SQL backends. Have you had any thoughts about this?
>>> I think the three options I included (CASCADE, RESTRICT, and SET_NULL)
>>> make sense for non-SQL backends, although I'd be glad to rename them and
>>> use non-SQL terminology.
>>
>> There are two aspects to consider - naming and functionality.
>
> So how about these options with this naming:
>
> CASCADE (or CASCADE_DELETE)
> PREVENT (or PREVENT_DELETE) (prevents anything from being deleted)
> SET_NONE
> SET_DEFAULT

I'm not wild about PREVENT, but it will do for now. There's a risk
that this will turn into a bikeshed argument; at this point, formal
acceptance of the concept and a working patch are much more important.

>> ~~~~~
>>
>> I'm broadly in favour of this proposal. There are some details that
>> may need to be sorted out, but they're mostly porcelain, not plumbing
>> - the core of the feature proposal itself is well defined.
>>
>> So, all that is left is to stick the ticket on the v1.2 Feature wiki
>> page so that it is considered when the time comes.
>
> Should I do this?

Yes. You want the feature, you advocate for it :-)

>> Also, keep working on the patch. I notice that the latest patch
>> doesn't contain any tests or documentation (although the earlier patch
>> contains tests) - both will be required before the feature lands.
>
> Really, the tests are missing? That was an accidental omission, then--I
> still have the tests running locally.
>
> Once we agree on naming changes, I'll work up a patch that implements
> only items 1-2, with the naming changes, including tests.
>
> What's the best way to add documentation? Should it be a patch against
> the existing docs?

Yes. The single patch should be ready to commit, with tests to prove
that the feature works, and any docs to tell people how to use it. My
work should be limited to "patch -p0 < cascade.diff && svn commit".

I've had a cursory glance at the patch. Some quick things that stood out:

* We are trying to keep SQL-specific stuff out of the codebase except
for the sql.Query backend. Defining CASCADE et all as classes that
contain SQL snippets isn't a good solution, as someone soon will be
trying to write a non-SQL backend, and will need to use the same
values. A simple constant will suffice.

* The value for on_delete should be set as a property of the field; if
there is a default, that default should be reflected on the field,
rather than interpreting a None value every time it is encountered.

* The patch makes reference to using MySQL error numbers. Erm... No. :-)

Yours,
Russ Magee %-)

hcarvalhoalves

unread,
Aug 14, 2009, 8:09:02 PM8/14/09
to Django developers
On Aug 13, 9:30 am, Russell Keith-Magee <freakboy3...@gmail.com>
wrote:
> On Thu, Aug 13, 2009 at 12:04 AM, Michael Glassford<glassfo...@gmail.com> wrote:
>
> Secondly: I'm sensitive to the extent that 'on delete cascade' et al
> are phrased in SQL specific terms. I fully acknowledge the use case -
> what happens to a FK when the object it points to is deleted - but I
> want to make sure that we phrase it in a way that makes sense with
> non-SQL backends. Have you had any thoughts about this?

Maybe using the UML terms to declare these associations, as it makes
sense in an ORM environment, and is not SQL specific.

ForeignKey(composition=True)
Strong association -> relates to SQL's CASCADE or similar behavior on
custom backends

ForeignKey(aggregation=True)
Weak association -> relates to SQL's SET_NULL or similar behavior on
custom backends

ForeignKey(restrict=True)
Optional restrict to raise Exception on delete -> relates to SQL's
RESTRICT


As a side note, I'm 100% in favor for a way of defining the on_delete
behavior at field declaration.

> Yours
> Russ Magee %-)

Russell Keith-Magee

unread,
Aug 14, 2009, 10:48:56 PM8/14/09
to django-d...@googlegroups.com
On Sat, Aug 15, 2009 at 8:09 AM, hcarvalhoalves<hcarval...@gmail.com> wrote:
>
> On Aug 13, 9:30 am, Russell Keith-Magee <freakboy3...@gmail.com>
> wrote:
>> On Thu, Aug 13, 2009 at 12:04 AM, Michael Glassford<glassfo...@gmail.com> wrote:
>>
>> Secondly: I'm sensitive to the extent that 'on delete cascade' et al
>> are phrased in SQL specific terms. I fully acknowledge the use case -
>> what happens to a FK when the object it points to is deleted - but I
>> want to make sure that we phrase it in a way that makes sense with
>> non-SQL backends. Have you had any thoughts about this?
>
> Maybe using the UML terms to declare these associations, as it makes
> sense in an ORM environment, and is not SQL specific.
>
> ForeignKey(composition=True)
> Strong association -> relates to SQL's CASCADE or similar behavior on
> custom backends
>
> ForeignKey(aggregation=True)
> Weak association -> relates to SQL's SET_NULL or similar behavior on
> custom backends
>
> ForeignKey(restrict=True)
> Optional restrict to raise Exception on delete -> relates to SQL's
> RESTRICT

This is an interesting idea - it's nicely object-based, and it gets
around the SQL-specific terminology. However, it does introduce some
nasty term-overloading with the phrase "aggregation".

However, the 'strong/weak' distinction is an interesting starting
point for some language. A proposal:

ForeignKey(XXX, association=STRONG)
- The current arrangement, equivalent to SQL ON DELETE CASCADE

ForeignKey(XXX, association=WEAK, null=True)
- The equivalent of SQL ON DELETE SET NULL

ForeignKey(XXX, association=WEAK, default=xxx)
- The equivalent of SQL ON DELETE SET DEFAULT

ForeignKey(XXX, association=PROTECTED)
- The equivalent of SQL ON DELETE RESTRICT. Deletion is prevented.

For completeness:

ForeignKey(XXX, association=WEAK)

would be an error, since the field doesn't allow NULLs, but an
alternate default value hasn't been specified.

Opinions?

Yours,
Russ Magee %-)

Michael Glassford

unread,
Aug 14, 2009, 10:57:41 PM8/14/09
to public-django-developer...@hugh.gmane.org

Russell Keith-Magee wrote:
> On Sat, Aug 15, 2009 at 8:09 AM, hcarvalhoalves<hcarvalhoalves-Re5...@public.gmane.org> wrote:
>> On Aug 13, 9:30 am, Russell Keith-Magee <freakboy3...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> wrote:

I think more people would understand the on_delete= than the
association= terminology without having to look it up; but I'd have no
problem implementing it this way if it's what gets decided on.

How would the equivalent of ON UPDATE be handled in this type of scheme,
assuming it gets added at some point?

Mike

Russell Keith-Magee

unread,
Aug 15, 2009, 9:08:23 AM8/15/09
to django-d...@googlegroups.com
On Sat, Aug 15, 2009 at 10:57 AM, Michael Glassford<glass...@gmail.com> wrote:
>
> Russell Keith-Magee wrote:
>> On Sat, Aug 15, 2009 at 8:09 AM, hcarvalhoalves<hcarval...@gmail.com> wrote:
>>> On Aug 13, 9:30 am, Russell Keith-Magee <freakboy3...@gmail.com>
>>> wrote:

Are you saying that a user who discovers on_delete=PREVENT in a model
won't need to do exactly the same thing? What does PREVENT mean? It
doesn't have an SQL equivalent - what is going to be prevented?

If you want to argue that association=STRONG et al is a bad conceptual
abstraction, thats fine. However, I won't accept the argument that
on_delete=CASCADE is better because it is somehow renders the user
immune from a need to read documentation. We _want_ users to read the
documentation on a feature before they use it. We _want_ to break the
assumptions they might bring with regard to SQL implementations.

> How would the equivalent of ON UPDATE be handled in this type of scheme,
> assuming it gets added at some point?

What aspect of ON UPDATE are you looking to implement? It isn't
immediately obvious to me that ON UPDATE is a good idea, or one that
has a natural object-based interpretation.

Yours,
Russ Magee %-)

Michael Glassford

unread,
Aug 15, 2009, 10:46:33 AM8/15/09
to public-django-developer...@hugh.gmane.org

Russell Keith-Magee wrote:


> On Sat, Aug 15, 2009 at 10:57 AM, Michael Glassford<glassfordm-Re5JQ...@public.gmane.org> wrote:
>> Russell Keith-Magee wrote:

>>> On Sat, Aug 15, 2009 at 8:09 AM, hcarvalhoalves<hcarvalhoalves-Re5...@public.gmane.org> wrote:
>>>> On Aug 13, 9:30 am, Russell Keith-Magee <freakboy3...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

True, they would have to look up PREVENT, but probably not CASCADE,
SET_NULL, or SET_DEFAULT.

> If you want to argue that association=STRONG et al is a bad conceptual
> abstraction, thats fine. However, I won't accept the argument that
> on_delete=CASCADE is better because it is somehow renders the user
> immune from a need to read documentation. We _want_ users to read the
> documentation on a feature before they use it. We _want_ to break the
> assumptions they might bring with regard to SQL implementations.

I'm not really arguing in favor of it, just mentioning that more people
will be familiar with the on_delete concept. At this point I don't have
a strong preference for either method over the other. I do think I would
prefer either method to nothing at all.

One more question that occurred to me this morning is, what would this do:

ForeignKey(XXX, association=WEAK, null=True, default=xxx)
- Is this the equivalent of SET NULL or SET DEFAULT?

>> How would the equivalent of ON UPDATE be handled in this type of scheme,
>> assuming it gets added at some point?
>
> What aspect of ON UPDATE are you looking to implement? It isn't
> immediately obvious to me that ON UPDATE is a good idea, or one that
> has a natural object-based interpretation.

I agree that it's less important and less obviously useful than ON
DELETE. I'll see if I can come up with a more compelling example, but
the way we've mainly used it is to set a lot of our foreign keys to
on_update=CASCADE. This is because the default SQL behavior when no ON
UPDATE clause is specified is to RESTRICT.

Mike

Russell Keith-Magee

unread,
Aug 15, 2009, 11:21:45 AM8/15/09
to django-d...@googlegroups.com
On Sat, Aug 15, 2009 at 10:46 PM, Michael Glassford<glass...@gmail.com> wrote:
>
> Russell Keith-Magee wrote:
>> On Sat, Aug 15, 2009 at 10:57 AM, Michael Glassford<glass...@gmail.com> wrote:
>>> Russell Keith-Magee wrote:
>>>> On Sat, Aug 15, 2009 at 8:09 AM, hcarvalhoalves<hcarval...@gmail.com> wrote:
>>>>> On Aug 13, 9:30 am, Russell Keith-Magee <freakboy3...@gmail.com>

SET DEFAULT. The SET-equivalent options are based entirely on the
value of `default`. The `null` argument doesn't affect this feature.
SET NULL is just the special case when you (implicitly or explicitly)
have default=None. Keep in mind that:

ForeignKey(XXX)

is actually an implicit version of:

ForeignKey(XXX, default=None)

but if you have default=None, you'd better have null=True as well, or
else you're going to get validation errors (since null=False is the
implicit setting).

Yes, this does mean you can't specify a default but have FK's reset to
NULL. However, to my mind, that's what a default means. Again - we're
not trying to reproduce SQL here, we're trying to come up with an
object model that makes sense.

Yours,
Russ Magee %-)

hcarvalhoalves

unread,
Aug 15, 2009, 1:45:44 PM8/15/09
to Django developers
On Aug 14, 11:48 pm, Russell Keith-Magee <freakboy3...@gmail.com>
wrote:
> On Sat, Aug 15, 2009 at 8:09 AM, hcarvalhoalves<hcarvalhoal...@gmail.com> wrote:
>
> > On Aug 13, 9:30 am, Russell Keith-Magee <freakboy3...@gmail.com>
> > wrote:
> >> On Thu, Aug 13, 2009 at 12:04 AM, Michael Glassford<glassfo...@gmail.com> wrote:
>
> >> Secondly: I'm sensitive to the extent that 'on delete cascade' et al
> >> are phrased in SQL specific terms. I fully acknowledge the use case -
> >> what happens to a FK when the object it points to is deleted - but I
> >> want to make sure that we phrase it in a way that makes sense with
> >> non-SQL backends. Have you had any thoughts about this?
>
> > Maybe using the UML terms to declare these associations, as it makes
> > sense in an ORM environment, and is not SQL specific.
>
> > ForeignKey(composition=True)
> > Strong association -> relates to SQL's CASCADE or similar behavior on
> > custom backends
>
> > ForeignKey(aggregation=True)
> > Weak association -> relates to SQL's SET_NULL or similar behavior on
> > custom backends
>
> > ForeignKey(restrict=True)
> > Optional restrict to raise Exception on delete -> relates to SQL's
> > RESTRICT
>
> This is an interesting idea - it's nicely object-based, and it gets
> around the SQL-specific terminology. However, it does introduce some
> nasty term-overloading with the phrase "aggregation".
>

This is UML, so anyone familiar with it understands Composition vs
Aggregation. It doesn't help if the person doesn't know UML, of
course, but I'm not just coming up with names of my own - it's an
industry standard. OTH, WEAK and STRONG are terms used neither by SQL
or UML, so I would be less in favor of using something like this.

I only see two options: either use standard terms that appear in
literature (hence my idea for UML terms), or phrase it in a way that
makes very clear what happens. E.g.:

ForeignKey(..., propagate_on_delete=True)
CASCADE

ForeignKey(..., propagate_on_delete=False, null=False)
RESTRICT

ForeignKey(..., propagate_on_delete=False, null=True)
SET NULL

ForeignKey(..., propagate_on_delete=False, default=XXX)
SET DEFAULT

ForeignKey(..., propagate_on_delete=False)
Raises Exception, need to define either "null" or "default"


I think it's a good middle-ground between the SQL-specific terms, Russ
ideas, and making sense on the documentation from the ORM point of
view.

Michael Glassford

unread,
Aug 15, 2009, 6:48:12 PM8/15/09
to django-d...@googlegroups.com

This eliminates the possibility of CASCADE when null=True or default=xxx
are specified, which I think goes to far. I prefer either

Michael Glassford

unread,
Aug 15, 2009, 6:55:42 PM8/15/09
to django-d...@googlegroups.com, public-public-django-developers-/JYPxA...@ciao.gmane.org
Michael Glassford wrote:
>
>
> hcarvalhoalves wrote:
>> On Aug 14, 11:48 pm, Russell Keith-Magee <freakboy3...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> wrote:
>>> On Sat, Aug 15, 2009 at 8:09 AM, hcarvalhoalves<hcarvalhoal...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>>
>>>> On Aug 13, 9:30 am, Russell Keith-Magee <freakboy3...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Drat, my email client sent this before I was finished with it. I was
going to say:

This eliminates the possibility of RESTRICT (not CASCADE) when null=True
or default=xxx
are specified, which I think goes to far. I prefer either Russell
Keith-Magee's original suggestion:

ForeignKey(XXX, association=STRONG)
- The current arrangement, equivalent to SQL ON DELETE CASCADE

ForeignKey(XXX, association=WEAK, null=True)
- The equivalent of SQL ON DELETE SET NULL

ForeignKey(XXX, association=WEAK, default=xxx)
- The equivalent of SQL ON DELETE SET DEFAULT

ForeignKey(XXX, association=PROTECTED)
- The equivalent of SQL ON DELETE RESTRICT. Deletion is prevented.

Or my original suggestion (using on_delete=CASCADE, SET_NULL,
SET_DEFAULT, PREVENT) or a modified version of my original suggestion to
make it more like the above by combining SET_NULL and SET_DEFAULT into a
single SET_VALUE (which would use default if available, otherwise would
set to None if null=True).

Drat

Russell Keith-Magee

unread,
Aug 15, 2009, 7:53:35 PM8/15/09
to django-d...@googlegroups.com

Yes. However, I challenge you to point at a single other place in
Django where UML notation or syntax is used. I'm sure COBOL has some
great turns of phrase too - doesn't mean we'll use them.

My issue isn't that Composition and Aggregation aren't good terms by
themselves. My problem is that we already have
Model.objects.aggregate() in the API, which has nothing to do with UML
or cascading deletes. We need to avoid naming collisions like this.

Yours,
Russ Magee %-)

hcarvalhoalves

unread,
Aug 16, 2009, 12:31:42 AM8/16/09
to Django developers
On Aug 15, 8:53 pm, Russell Keith-Magee <freakboy3...@gmail.com>
wrote:
The point is, using terms that are agreed upon. My idea was using UML
terms, which is a standard in OO modeling, the same way as ForeignKey
is used, which is a term from ER modeling. I don't know what you tried
by comparing UML to COBOL, but I'm not even going further on this
because...

> My issue isn't that Composition and Aggregation aren't good terms by
> themselves. My problem is that we already have
> Model.objects.aggregate() in the API, which has nothing to do with UML
> or cascading deletes. We need to avoid naming collisions like this.

... you're right, I forgot that the term is used in other context for
the ORM already.

Anyway, I insist on using known, widespread terms for this as possible.

Russell Keith-Magee

unread,
Aug 16, 2009, 8:11:10 PM8/16/09
to django-d...@googlegroups.com

I introduced COBOL because it has about as much relevance to Python as
UML does.

>> My issue isn't that Composition and Aggregation aren't good terms by
>> themselves. My problem is that we already have
>> Model.objects.aggregate() in the API, which has nothing to do with UML
>> or cascading deletes. We need to avoid naming collisions like this.
>
> ... you're right, I forgot that the term is used in other context for
> the ORM already.
>
> Anyway, I insist on using known, widespread terms for this as possible.

Firstly - you can insist all you like, but I'm the one with commit access. :-)

Secondly, Weak and Strong _are_ widespread terms. They are used in
Python and a number of other OO languages when used to refer to object
references.

Thirdly, at some point, this becomes a bikeshed. I'm willing to
entertain discussion on finding a good term, but at some point we have
to just choose something and move on.

Yours,
Russ Magee %-)

Martin Maney

unread,
Aug 17, 2009, 12:11:34 AM8/17/09
to django-d...@googlegroups.com
On Sat, Aug 15, 2009 at 10:45:44AM -0700, hcarvalhoalves wrote:
> ForeignKey(..., propagate_on_delete=True)
> CASCADE
>
> ForeignKey(..., propagate_on_delete=False, null=False)
> RESTRICT
>
> ForeignKey(..., propagate_on_delete=False, null=True)
> SET NULL
>
> ForeignKey(..., propagate_on_delete=False, default=XXX)
> SET DEFAULT
>
> ForeignKey(..., propagate_on_delete=False)
> Raises Exception, need to define either "null" or "default"

+0.9

I found the "association" style both unfamiliar and, frankly, a bit
precious, but this is brilliant. I especially like the way it gives an
explicit name to the most important aspect of it: whether FK
dependencies cause an entity's deletion to propagate recursively or
not.

Well, that part is brilliant. I think you're simply wrong about that
error case: without overriding the defaults, null=False and
default=None, you have the second case, and should get RESTRICT
behaviour. And as Russ (I think it was) pointed out, if a default
value is given the null setting doesn't matter. So in a compressed
logic table form:

PoD default null default action
T * * CASCADE
F <value> * SET DEFAULT
F none T SET NULL
F none F RESTRICT

> I think it's a good middle-ground between the SQL-specific terms, Russ
> ideas, and making sense on the documentation from the ORM point of
> view.

With that minor course correction, I agree.

--
The Internet discourages reflection and deep thought. It
encourages just glossing over, as quick as possible. The
Internet is a terrific way to look up facts and a terrible
way to get a story. -- Clifford Stoll

Michael Glassford

unread,
Aug 17, 2009, 10:41:08 AM8/17/09
to public-django-developer...@hugh.gmane.org

Martin Maney wrote:
> On Sat, Aug 15, 2009 at 10:45:44AM -0700, hcarvalhoalves wrote:
>> ForeignKey(..., propagate_on_delete=True)
>> CASCADE
>>
>> ForeignKey(..., propagate_on_delete=False, null=False)
>> RESTRICT
>>
>> ForeignKey(..., propagate_on_delete=False, null=True)
>> SET NULL
>>
>> ForeignKey(..., propagate_on_delete=False, default=XXX)
>> SET DEFAULT
>>
>> ForeignKey(..., propagate_on_delete=False)
>> Raises Exception, need to define either "null" or "default"
>
> +0.9
>
> I found the "association" style both unfamiliar and, frankly, a bit
> precious, but this is brilliant. I especially like the way it gives an
> explicit name to the most important aspect of it: whether FK
> dependencies cause an entity's deletion to propagate recursively or
> not.

> Well, that part is brilliant. I think you're simply wrong about that
> error case:

If this is a response to my comment that "This eliminates the
possibility of RESTRICT... when null=True or default=xxx", then...

> without overriding the defaults, null=False and
> default=None, you have the second case, and should get RESTRICT
> behaviour. And as Russ (I think it was) pointed out, if a default
> value is given the null setting doesn't matter. So in a compressed
> logic table form:
>
> PoD default null default action
> T * * CASCADE
> F <value> * SET DEFAULT
> F none T SET NULL
> F none F RESTRICT
>

...I already understood what you say here. What I meant was, with the
other suggested notations, it is possible to use RESTRICT even with
foreign keys that have null=True and/or default=xxx; with this notation,
it is not. I think that's a bad thing. While I agree that this notation
has a certain elegance to it, it also limits the available options more
than the other suggested notations--too much, in my opinion. I fail to
see how it's an improvement on, say:

ForeignKey(..., on_delete=PROPAGATE)
CASCADE
ForeignKey(..., on_delete=SET_VALUE, null=True)
SET NULL
ForeignKey(..., on_delete=SET_VALUE, default=xxx)
SET VALUE
ForeignKey(..., on_delete=PROTECT)
RESTRICT

This is both at least as explicit as and more flexible than your example
above. (Note that I used on_delete=PROPAGATE instead of
on_delete=CASCADE, which is what I originally suggested, simply to match
your use of the term "propagate" in your example above).

Mike

Jacob Kaplan-Moss

unread,
Aug 17, 2009, 10:46:05 AM8/17/09
to django-d...@googlegroups.com
Hi folks --

Y'know, there's quite a bit of bike-shedding going on in this
discussion, and not a whole lot of code writing. Remember that our
general policy is that whoever builds the shed gets to paint it; y'all
might want to spend some of this energy actually working on a patch.

Jacob

Michael Glassford

unread,
Aug 17, 2009, 11:03:03 AM8/17/09
to public-django-developer...@hugh.gmane.org

Actually, I *am* working patch, which is a modification of the patch I
previously submitted. I'm trying to figure out what would be the best
approach before submitting it.

Mike

hcarvalhoalves

unread,
Aug 18, 2009, 11:09:18 AM8/18/09
to Django developers
On Aug 17, 1:11 am, Martin Maney <ma...@two14.net> wrote:
> On Sat, Aug 15, 2009 at 10:45:44AM -0700, hcarvalhoalves wrote:
> > ForeignKey(..., propagate_on_delete=True)
> > CASCADE
>
> > ForeignKey(..., propagate_on_delete=False, null=False)
> > RESTRICT
>
> > ForeignKey(..., propagate_on_delete=False, null=True)
> > SET NULL
>
> > ForeignKey(..., propagate_on_delete=False, default=XXX)
> > SET DEFAULT
>
> > ForeignKey(..., propagate_on_delete=False)
> > Raises Exception, need to define either "null" or "default"
>
> +0.9
>
> I found the "association" style both unfamiliar and, frankly, a bit
> precious, but this is brilliant.  I especially like the way it gives an
> explicit name to the most important aspect of it: whether FK
> dependencies cause an entity's deletion to propagate recursively or
> not.
>
> Well, that part is brilliant.  I think you're simply wrong about that
> error case: without overriding the defaults, null=False and
> default=None, you have the second case, and should get RESTRICT
> behaviour.

My fear was making it too subtle to know what will happen without null
or default. But you're right; just assuming the defaults is correct.

I hope this idea helps you avoiding SQL-specific terms on the patch,
I'm looking forward to see it accepted ;)

drakkan

unread,
Aug 18, 2009, 1:43:17 PM8/18/09
to Django developers
Hey guys,

not a flame only a consideration: the best python orm/sql toolkit
(sqlalchemy) already support this and many many other features/
database engines, why not move the efforts in sa integration? Using sa
in django is simple but actually you cannot use admin interface

James Bennett

unread,
Aug 18, 2009, 1:57:41 PM8/18/09
to django-d...@googlegroups.com
Please don't feed the troll.


--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."

Russell Keith-Magee

unread,
Aug 18, 2009, 8:16:36 PM8/18/09
to django-d...@googlegroups.com
On Wed, Aug 19, 2009 at 1:43 AM, drakkan<drakk...@gmail.com> wrote:
>
> Hey guys,
>
> not a flame only a consideration: the best python orm/sql toolkit
> (sqlalchemy) already support this and many many other features/
> database engines, why not move the efforts in sa integration? Using sa
> in django is simple but actually you cannot use admin interface

On the off chance that this was a well intentioned comment, and not
just at troll, I will point out that:

* "Best Python ORM/SQL toolkit" is a _huge_ value judgement.

* SQLAlchemy has explicitly stated that they aren't going to attempt
to solve one of the problems that Django is explicitly trying to
target - support for non-relational data stores. We aren't going to
adopt a toolkit that has said they aren't going to address a problem
we want to solve.

That said, James is correct that this isn't a topic that requires debate.

Yours,
Russ Magee %-)

drakkan

unread,
Aug 19, 2009, 6:33:15 AM8/19/09
to Django developers
Sorry my intention was not a flame,

I commented only beacause recently I switched a my big project from
django orm to sqlalchemy for the following reasons:

1) on delete behaviuor control
2) with sqlalchemy eagerload is ever possible, if you need, get a
whole graph of object with only one query, django has some limitations
with many to many relation and select_related
3) sa has support for multiple database, django maybe will support
multi db in 1.2 (soc project)
4) sa has support for connection pools, with django you have to use
external tool (for examples pgpool for postgres)
5) with sa if you have several threads you can use the scoped_session
(a new session for every thread) or decide to share the same session
(at your risk, if you know what you are doing) between several
threads, django open ever a new session for every thread and is not
customizable
6) with sa you have out of box fine control over commit and rollback
with django you have to use commit_manually to have the same behaviour
(sa way is more cleaner in my opinion)
7) sa support more database engine (for example mssql)

that said django orm is much simple to learn than sa, I hope django
orm will become soon better than sa,

drakkan

On 19 Ago, 02:16, Russell Keith-Magee <freakboy3...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages