Jak pyta tytuł, dlaczego chłopaki z Django zdecydowali się zaimplementować obiekt request.POST za pomocą querydict (co oczywiście sprawia, że całość jest niezmienna?)
Wiem, że możesz to zmienić , wykonując kopię danych postu
post = request.POST.copy()
ale dlaczego to robisz? Z pewnością prościej byłoby po prostu pozwolić, aby i tak było to zmienne? A może jest używany również z innego powodu, który może powodować problem?
request.POST
zostało przesłane z większą ilością danych niż w rzeczywistości.Odpowiedzi:
To trochę tajemnica, prawda? Kilka powierzchownie wiarygodnych teorii okazuje się błędnych w badaniu:
Aby
POST
obiekt nie musiał implementować metod mutacji? Nie:POST
przedmiot należący dodjango.http.QueryDict
klasy , która implementuje pełen zestaw metod mutacji tym__setitem__
,__delitem__
,pop
iclear
. Implementuje niezmienność, sprawdzając flagę podczas wywoływania jednej z metod mutacji. A kiedy wywołaszcopy
metodę, otrzymasz kolejnąQueryDict
instancję z włączoną flagą mutable.Aby poprawić wydajność? Nie:
QueryDict
klasa nie zyskuje na wydajności, gdy flaga mutacji jest wyłączona.Aby
POST
obiekt mógł służyć jako klucz słownika? Nie:QueryDict
obiekty nie podlegają hashowaniu.Aby
POST
dane mogły być budowane leniwie (bez zobowiązania się do przeczytania całej odpowiedzi), jak tu twierdzono ? Nie widzę tego dowody w kodzie: o ile mogę powiedzieć, cała odpowiedź jest zawsze czytać, albo bezpośrednio , albo za pośrednictwemMultiPartParser
zamultipart
odpowiedzi.Aby uchronić Cię przed błędami programistycznymi? Widziałem, jak to twierdzono, ale nigdy nie widziałem dobrego wyjaśnienia, czym są te błędy i jak niezmienność chroni cię przed nimi.
W każdym razie,
POST
to nie zawsze niezmienne : gdy odpowiedź jestmultipart
, toPOST
jest zmienny. To wydaje się stawiać kibosha na większości teorii, o których możesz pomyśleć. (Chyba że takie zachowanie jest przeoczeniem).Podsumowując, nie widzę jasnego uzasadnienia w Django, aby
POST
obiekt był niezmienny dla nie-multipart
żądań.źródło
Jeśli żądanie było wynikiem
form
przesłania Django , wówczas POSTimmutable
powinien zapewnić integralność danych między wysłaniem formularza a walidacją formularza . Jeśli jednak żądanie nie zostało wysłane za pośrednictwem przesłania Djangoform
, POST jest,mutable
ponieważ nie ma walidacji formularza.Zawsze możesz zrobić coś takiego: (zgodnie z komentarzem @ leo-the-manic )
źródło
Aktualizacja :
Gareth Rees miał rację, że punkty 1 i 3 nie były ważne w tym przypadku. Chociaż myślę, że punkty 2 i 4 są nadal aktualne, dlatego tezy zostawię tutaj.
(Zauważyłem, że
request.POST
obiekt zarówno Pyramid (Pylon), jak i Django jest jakąś formąMultiDict
. Więc być może jest to bardziej powszechna praktyka niż uczynienierequest.POST
niezmiennym.)Nie mogę mówić w imieniu chłopaków z Django, chociaż wydaje mi się, że może to z kilku następujących powodów:
Wydajność . Niezmienne obiekty są „szybsze” niż zmienne, ponieważ pozwalają na znaczące optymalizacje. Obiekt jest niezmienny, co oznacza, że możemy przydzielić mu miejsce w czasie tworzenia , a wymagania przestrzenne się nie zmieniają. Z tego powodu ma również takie rzeczy, jak wydajność kopiowania i wydajność porównania.Edycja : tak nie jest,QueryDict
jak wskazał Gareth Rees.request.POST
wydaje się, że żadna aktywność po stronie serwera nie powinna powodować konieczności zmiany danych żądania . A zatem niezmienne obiekty są bardziej odpowiednie, nie wspominając o tym, że mają znaczną przewagę wydajnościową.Niezmienne obiekty mogą być używane jakoEdit : moja pomyłka, niezmienne bezpośrednio nie sugerować hashable ; obiekty, które można mieszać , są jednak również zwykle niezmienne .dict
klucze, które ja przypuszczam może być bardzo przydatna gdzieś w Django ..request.POST
(szczególnie do wtyczek innych firm i poza nimi), możesz spodziewać się, że obiekt żądania od użytkownika pozostanie niezmieniony.W pewnym sensie te powody są również ogólnymi odpowiedziami na pytanie „niezmienny czy zmienny?” pytanie. Jestem pewien, że w przypadku Django istnieje znacznie więcej rozważań projektowych niż powyżej.
źródło
sessions
krótkotrwały sposób uzyskiwania i modyfikowania danych między stanami.POST
jestQueryDict
obiektem , a te obiekty nie mają żadnej korzyści z wydajności, będąc niezmiennymi. Twój punkt (3) nie może być odpowiedzią, ponieważQueryDict
obiekty nie są hashowane, a więc nie mogą być używane jako klucze słownikowe.QueryDict
zanim odpowiedziałem.requests.POST._mutable = True; requests.POST['foo'] = 'bar'; request.POST._mutable = False
Podoba mi się, że domyślnie jest niezmienny. Jak wskazano, możesz uczynić go zmiennym, jeśli potrzebujesz, ale musisz to wyraźnie powiedzieć. To coś w stylu „Wiem, że debugowanie formularza może stać się koszmarem, ale wiem, co teraz robię”.
źródło
Znalazłem to w komentarzu do odpowiedzi stosu https://stackoverflow.com/a/2339963
źródło
Uwaga:
multipart
żądania są niezmienne od wersji 1.11 Django https://github.com/django/django/blob/stable/1.11.x/django/http/multipartparser.py#L292W poprzednich wersjach były zmienne.
źródło