• 24 maja 2023 16:05

    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:

    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ę.

  • 30 maja 2023 12:40

    Jest też krótka dyskusja na grupie django-developers o tym: groups.google.com/g/django-developers/c/Sxj7eS7-8SQ/m/nfgIG92vAAAJ

    TL;DR devy widzą problem w sytuacji kiedy ktoś będzie migrował aplikacje z obecnych kaskad do nowych, tylko w bazie, bo trzeba będzie zmienić wszystkie relacje do modelu, do tego brak odpalanych sygnałów może zepsuć gotowe aplikacje które na nich polegają. Więc chcą aby przed usunięciem obiektów Django i tak odpalało collector dla powiązań wraz z sygnałami.

    Wygląda na to że najlepszym rozwiązaniem problemu collectora jest zrobienie własnego ForeignKey i delete() które nie odpalają logiki Django tylko uderzają odrazu do bazy danych.

  • 30 maja 2023 21:49

    Ten temat może jeszcze nie być rozwiązany przez następne 15 lat. Moim zdaniem rozwiązaniem problemu collectora jest nie używanie collectora czyli CASCADE w Django.
    Najprostszym rozwiązaniem jest zamienienie wszystkich CASCADE na PROTECT i napisanie metody, która będzie robić usuwanie danych zgodnie ze sztuką, czyli usuwać bulkiem dane z odpowiednich modeli. Przy takim rozwiązaniu będziesz spał spokojnie przez następne kilka lat i nie martwił się co nowego/ciekawego devy Dj zaimplementują.

  • 1 czerwca 2023 21:48

    Chciałem napisać że z PROTECT mam ten problem że np. przy usuwaniu usera w Misago trzeba potencjalnie pierdyliard relacji ręcznie zupdatować na NULL co spowoduje tonę operacji zapisu w PostgreSQL'u, ale przecież CASCADE też wykona te operacje bo wiersze w PostgreSQLu nigdy nie są zmieniane na dysku tylko kopiowane wraz ze zmianami.

    ...chociaż benefit jest taki że CASCADE zrobi całość tej roboty po stronie bazy danych, a tak trzeba strzelać zapytaniami z Django co przy wielu tabelach swoje zrobi.

  • 15 października 2023 19:02

    Do Django 5.0 rozwiązanie nie weszło, śmiałek nadal dzielnie walczy po 5 miesiącach. Może rozwiązanie się pojawi w wersji 5.2.

  • 20 grudnia 2023 14:14

    Aktualny status PR'a to "czeka na review od Django Fellowa". Więc jest szansa że pojawi się to w Django 5.2.

    Co prawda, dalej będzie odpalana ta magiczna emulacja kaskady po stronie Django, ale po tej zmianie będzie ona pomijać relacje które zostały oddelegowane do bazy danych. Więc będzie można ją ominąć przez własne funkcje do usuwania pomijające maszynerię Django i wysyłające query DELETE FROM ... WHERE bezpośrednio do bazy danych. Taki mam plan w przyszłości w Misago.

  • 19 grudnia 2024 11:35

    Nadal obserwujemy i trzymamy kciuki za powodzenie. Już była przymiarka w wersji 5.1 do wprowadzenia ale nie przeszło. Śmiałek dzielnie walczył do kwietnia tego roku ale od 8 mcy brak zmian. Ciekawe czy kolejny contrybutor "polegnie" w boju ze środowiskiem Django (kodem i ludźmi) czy wytrwa do końca. Czekamy na wersje 5.2 (kwiecień/maj 2025)