Kij w mrowisko: Django Sprint 2014, Kraków
15 i 16 lutego 2014 odbył się Django Sprint w Krakowie, na którym najlepsi programiści Python poprawiali błędy Django. A ja zapytuję - po co poprawiać coś, co jest w wielu miejscach źle zrealizowane “by design”?
Oczywiście przesadzam, ale nie mogę oprzeć się krytyce, skoro na prawdę istotne wady Django nie są korygowane a istotne feature requesty są odrzucane za “niezgodność z Django ethos”. Kilka najbardziej irytujących błędów i braków na mojej liście:
Brak model.reload()
Odświeżenie properties obiektu jest czasem konieczne, bo DjangoORM nie ma sensownego persistence managera (błąd projektowy polega na własnej i przeciętnej implementacji ORM, zamiast zastosowania sprawdzonych wzorców lub gotowych rozwiązań).
Obecnie trzeba obchodzić przez sekwencję:
obj = Model.objects.get(pk=obj.pk)
Skopany transaction management
Do v1.6 mamy do dyspozycji dekoratory commit_on_success
oraz commit_manually
, a także low-level API z funkcjami commit
, rollback
, savepoint
. Problemy są następujące:
-
obsługa
commit_manually
sprowadza się do zabawy w dostawianie rollbacków i commitów w odpowiednich miejscach, np. przed/po response, w przeciwnym razie otrzymujemyTransactionManagementError
z poziomu template/middleware. -
przy
commit_manually
każdy wyjątek opakowywany jest wTransactionManagementError
, więc trzeba używać debuggera lub usuwać wsparcie dla transakcji, aby dowiedzieć się o szczegółach błędu (sic!) -
od wersji 1.6 mamy
atomic
, który zastępuje powyższe funkcje i upraszcza obsługę transakcji, ale od v1.8 nie będzie już żadnej możliwości niskopoziomowego kontrolowania transakcji (będzie prościej i jednoznacznie, ale ze związanymi rękoma) -
wsparcie multidb jest skopane, więc szereg funkcji i metod ma dodatkowy parametr
using
, który domyślnie oznacza bazędefault
. W przypadku dekoratorów i funkcji związanych z transakcjami ma to fatalny skutek w postaci zarządzania wyłącznie transakcjami dla bazy domyślnej, ale niekoniecznie używanej w danym widoku (!!!), chyba że jawnie użyje się N dekoratorów dla wszystkich używanych baz (to nie jest czytelne i takie oczywiste, szczególnie przy class-based views).
Formularze spaghetti
Związek formularzy z HTML (widgetami) to fatalny błąd projektowy. Formularze służą walidacji i czyszczeniu danych i czasem zawierają w sobie jakieś konkretne operacje (np. form.save
). Niestety każdy field jest ściśle związany ze swoim widgetem HTML, co widać wyraźnie przy próbie odczytania błędów formularza, gdzie jako reprezentację ciągu otrzymujemy HTML! Implementując RESTful service albo jakąkolwiek inną usługę nie związaną z HTML borykamy się z bagażem zależności, które trzeba sprytnie omijać.
Widgety zaimplementowane są w stylu “spaghetti” - w kodzie pythona odnajdujemy rzeź generującą koślawe HTML-e (nienależyta separacja prezentacji od kontrolera). Aby dostosować prezentację trzeba uciekać się do pakietów rozszerzających możliwości parametryzowania prezentacji (Uniform , Crispy forms ), ale one też ostatecznie nie są elastycznym i poprawnym rozwiązaniem. Problemy wynikają właściwie z nieco ułomnego systemu szablonów (zbyt wiele działań oddelegowanych jest do helperów).
Wadliwa jest obsługa pól, gdzie definicja Meta.fields jest “magicznie” uzupełniana o wszystkie pola dodane w klasie formularza. Dziedziczenie po takim formularzu uniemożliwia proste ograniczanie używanych pól i trzeba usuwać je w __init__()
.
Wadliwa jest obsługa formularzy bez pól, w przypadku których Django zakłada zawsze brak błędów, mimo zdefiniowania metody clean ze ścisłymi regułami!
Ograniczony system szablonów
Django ethos
nie pozwala na dostarczenie tak podstawowego template taga czy rozwiązania, jakim jest dostęp do danych przez klucz/indeks określony zmienną. Za każdym razem trzeba pisać swój template tag lookup
czy get_key
.
Ze względu na strukturę ograniczone są możliwości łatwej wizualizacji bardziej skomplikowanych obiektów, jak np. formularzy.
Co robić, wuju?
Jak radzić sobie z Django w prawdziwych projektach podpowiada Christophe Pettus z PostgreSQL Experts, Inc w PDF Unbreaking Django