django-why is the request.POST obiekt niezmienny?

Jak pyta tytuł, dlaczego chłopaki z Django zdecydowali się zaimplementować żądanie.POST obiekt z querydict (co oczywiście z kolei sprawia, że całość jest niezmienna?)

Wiem, że możesz zmutować to wykonując kopię danych posta

post = request.POST.copy()
Ale dlaczego to robisz? Z pewnością byłoby prościej po prostu pozwolić, aby to coś było mutowalne? A może jest używany z jakiegoś innego powodu, który może powodować problemy?
 92
Author: bharal, 2012-09-27

6 answers

To trochę zagadka, prawda? Kilka powierzchownie wiarygodnych teorii okazuje się błędnych w śledztwie: {]}

  1. Aby obiekt POST nie musiał implementować metod mutacji? No: obiekt POST należy do django.http.QueryDict klasa , która implementuje pełny zestaw metod mutacji, w tym __setitem__, __delitem__, pop i clear. Implementuje niezmienność, sprawdzając flagę podczas wywoływania jednej z metod mutacji. A kiedy wywołujesz metodę copy, Pobierz kolejną instancję QueryDict z włączoną zmienną flagą.

  2. Dla poprawy wydajności? Nie: klasa QueryDict nie zyskuje żadnych korzyści z wydajności, gdy zmienna flaga jest wyłączona.

  3. Aby obiekt POST mógł być użyty jako klucz słownikowy? Nie: QueryDict obiekty nie są hashowalne.

  4. Aby POST dane mogły być budowane leniwie (bez konieczności odczytywania całej odpowiedzi), jak tu twierdzisz? Nie widzę na to żadnych dowodów w kod: z tego co wiem, cała odpowiedź jest zawsze czytana, albo bezpośrednio, albo poprzez MultiPartParser dla multipart odpowiedzi.

  5. Aby chronić Cię przed błędami programistycznymi? Widziałem to twierdzenie, ale nigdy nie widziałem dobrego wyjaśnienia, czym są te błędy i jak niezmienność chroni przed nimi.

W każdym przypadku POST jest nie zawsze niezmienne : gdy odpowiedź jest multipart, to POST jest zmienna. To wydaje się wykorzystaj większość teorii, które możesz wymyślić. (Chyba, że to zachowanie jest niedopatrzeniem.)

W podsumowaniu, nie widzę jasnego uzasadnienia w Django dla POST obiektu, który ma być niezmienny dla żądań nie-multipart.

 118
Author: Gareth Rees,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:15

Jeśli żądanie było wynikiem Django form złożenia, wówczas rozsądne jest, aby POST był immutable aby zapewnić integralność danych pomiędzy formularzem przekazaniem a formularzem walidacją . Jednakże, jeśli żądanie było a nie wysłane przez Django form submission, then POST is mutable ponieważ nie ma walidacji formularza.

Zawsze możesz zrobić coś takiego: (jak na @ leo-the-manic ' s komentarz )

#  .....
mutable = request.POST._mutable
request.POST._mutable = True
request.POST['some_data'] = 'test data'
request.POST._mutable = mutable
# ......
 75
Author: un33k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:54

Update :

Gareth Rees miał rację, że pkt 1 i 3 nie były ważne w tym przypadku. Choć myślę, że punkt 2 i 4 są nadal aktualne, dlatego zostawię tutaj tezy.

(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ż uczynienie request.POST niezmiennym.)


Nie mogę mówić za chłopaków z Django, chociaż wydaje mi się, że mogło to być z powodu niektórych z tych uzasadnienie:

  1. Performence . obiekty niezmienne są "szybsze" nad zmiennymi, ponieważ pozwalają na znaczne optymalizacje. Obiekt jest niezmienny oznacza, że możemy przeznaczyć dla niego przestrzeń w czasie tworzenia , a wymagania przestrzeni nie ulegają zmianie. Ma również takie rzeczy, jak wydajność kopiowania i wydajność porównywania z tego powodu. Edit : tak nie jest w przypadku QueryDict, Jak zauważył Gareth Rees.
  2. W przypadku request.POST, to wydaje się, że żadna aktywność po stronie serwera nie powinna zmieniać danych żądania . I dlatego obiekty niezmienne są bardziej odpowiednie, nie wspominając o tym, że mają znaczną przewagę wydajności.
  3. Obiekty niezmienne mogą być używane jako klucze dict, co przypuszczam, że może być bardzo przydatne gdzieś w Django.. Edit : mój błąd, niezmienny nie implikuje bezpośrednio ; hashable obiekty są jednak zazwyczaj niezmienne jak również.
  4. kiedy przekazujesz request.POST (zwłaszcza wtyczkom innych firm i wtyczkom), możesz oczekiwać, że ten obiekt żądania od użytkownika pozostanie niezmieniony.

W jakiś sposób te powody są również ogólnymi odpowiedziami na "immutable vs mutable?"pytanie. Jestem pewien, że w przypadku Django jest o wiele więcej rozważań projektowych niż powyżej.

 5
Author: K Z,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-27 15:52:08

Podoba mi się, że domyślnie jest niezmienny. Jak wspomniano, możesz uczynić go zmiennym, jeśli potrzebujesz, ale musisz być o tym szczery. To jest jak " Wiem, że mogę zrobić mój formularz debugowania koszmar, ale wiem, co robię teraz.'

 3
Author: pawelmech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-17 15:24:13

Znalazłem to w komentarzu do Stack Answer https://stackoverflow.com/a/2339963

I musi być niezmienna, aby można było ją budować leniwie. Kopiowanie wymusza uzyskanie wszystkich danych POST. Do momentu otrzymania kopii może nie być ona pobrana. Co więcej, aby wielowątkowy serwer WSGI działał rozsądnie dobrze, pomocne jest, jeśli jest to niezmienne

 2
Author: Seaux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:43

Uwaga: multipart żądania są niezmienne od Django 1.11 https://github.com/django/django/blob/stable/1.11.x/django/http/multipartparser.py#L292

Były mutowalne w poprzednich wersjach.

 0
Author: Alex Paramonov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-12 10:40:07