Jednym z mniej znanych ograniczeń Django jest brak obsługi kaskad po stronie bazy danych przy operacjach usuwania.
Dokumentacja Django pisze:
When Django deletes an object, by default it emulates the behavior of the SQL constraint ON DELETE CASCADE – in other words, any objects which had foreign keys pointing at the object to be deleted will be deleted along with it. For example:
Kiedy robimy delete()
na modelu który ma zdefiniowane relacje do innych modeli, Django tworzy specjalny obiekt, Collector
. Collector
następnie zbiera informacje o powiązanych z naszym obiektem modelach oraz dalej, modelach powiązanych z tymi modelami, i usuwa je, przy okazji wysyłając sygnały pre_delete
i (od wersji 4.2) post_delete
.
Powyższe podejście potrafi być boleśnie powolne (albo w ogóle nie działać) przy większych bazach danych, dlatego już 9 lat temu pojawił się ticket z prośbą dodania do Django prawdziwych kaskad działających po stronie bazy danych.
W przeszłości było do tego kilka podejść, jednak żadne nie zakończyło się sukcesem:
- github.com/django/django/pull/8661 (2017 - 2020)
- github.com/django/django/pull/14550 (2021)
Kilka tygodni temu pojawił się nowy śmiałek: github.com/django/django/pull/16851
Chciałbym to w końcu zobaczyć w Django bo na kilku projektach mam scenariusze gdzie usuwam obiekty z którymi powiązane są masy danych (np. konta użytkowników, kategorie), i w różnych projektach różnie to obchodzę.