-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
Fixed #21961 -- Added support for database-level delete options for ForeignKey. #19925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
f816238
to
febec5c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple minor suggestions.
febec5c
to
8a0c034
Compare
a7af053
to
42bde24
Compare
42bde24
to
70080f3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great. Took a look at docs and a first look at the implementation.
I think changes are pending to the system checks. When that's in, I'll look at that, the tests, the django.contrib changes, and do some manual testing.
68884c1
to
1ffc225
Compare
4bc3363
to
9353da6
Compare
2b744df
to
6bea938
Compare
from django.core.checks import Warning as DjangoWarning | ||
from django.db import connection, models | ||
from django.test.testcases import SimpleTestCase | ||
from django.test import skipUnlessDBFeature |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to your changes but this module should be named test_related_fields
, there's no such thing as a relative field 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch 🎯 Let's rename it when this is merged.
6bea938
to
0ef3064
Compare
0ef3064
to
81ea5a7
Compare
…oreignKey. Thanks Simon Charette for pair programming. Co-Authored-By: Nick Stefan <NickStefan12@gmail.com> Co-Authored-By: Akash Kumar Sen <71623442+Akash-Kumar-Sen@users.noreply.github.com> Co-Authored-By: Simon Charette <charette.s@gmail.com>
81ea5a7
to
47446e3
Compare
buildbot, test on oracle. |
cd45cf6
to
0664b7f
Compare
0664b7f
to
74adb91
Compare
buildbot, test on oracle. |
def __init__(self, *args, **kwargs): | ||
kwargs.setdefault("force_collection", True) | ||
super().__init__(*args, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not put this in the signature?
def __init__(self, *args, **kwargs): | |
kwargs.setdefault("force_collection", True) | |
super().__init__(*args, **kwargs) | |
def __init__(self, *args, force_collection=True, **kwargs): | |
super().__init__(*args, force_collection=force_collection, **kwargs) |
"The model cannot have both related fields with " | ||
"database-level and python-level on_delete variants.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar fix:
"The model cannot have both related fields with " | |
"database-level and python-level on_delete variants.", | |
"The model cannot have related fields with both " | |
"database-level and python-level on_delete variants.", |
If ``DB_*`` options are used, Django doesn't need to fetch objects into memory | ||
to send signals and handle cascades. However, if there are no cascades and no | ||
signals, then Django may take a fast-path and delete objects without fetching | ||
into memory. For large deletes this can result in significantly reduced memory | ||
usage. The amount of executed queries can be reduced, too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current edit doesn't really make sense: "However, ..." doesn't connect. My attempt to clarify:
If ``DB_*`` options are used, Django doesn't need to fetch objects into memory | |
to send signals and handle cascades. However, if there are no cascades and no | |
signals, then Django may take a fast-path and delete objects without fetching | |
into memory. For large deletes this can result in significantly reduced memory | |
usage. The amount of executed queries can be reduced, too. | |
Django won’t need to fetch objects into memory when deleting them in two cases: | |
1. If related fields use ``DB_*`` options. | |
2. If there are no cascades and no delete signal receivers. | |
In these cases, Django may take a fast path and delete objects without fetching | |
them, which can result in significantly reduced memory usage and fewer executed | |
queries. |
* **models.E049**: The model cannot have both related fields with | ||
database-level and python-level ``on_delete`` variants. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* **models.E049**: The model cannot have both related fields with | |
database-level and python-level ``on_delete`` variants. | |
6D38 | * **models.E049**: The model cannot have related fields with both |
database-level and python-level ``on_delete`` variants. |
The database variants are more efficient because they avoid fetching related | ||
objects, but ``pre_delete`` and ``post_delete`` signals won't be sent when | ||
:attr:`~django.db.models.DB_CASCADE` is used. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can spell out how they work a bit more, to help readers with some SQL knowledge make the connection, and to promote the feature.
The database variants are more efficient because they avoid fetching related | |
objects, but ``pre_delete`` and ``post_delete`` signals won't be sent when | |
:attr:`~django.db.models.DB_CASCADE` is used. | |
These options handle deletion logic entirely within the database, using the SQL | |
``ON DELETE`` clause. They are thus more more efficient than the existing | |
Python-level options, as Django does not need to load objects before deleting | |
them. As a consequence, the :attr:`~django.db.models.DB_CASCADE` option does | |
not trigger the ``pre_delete`` or ``post_delete`` signals. |
ticket-21961