Django - почему объект request.POST неизменяем?

Как говорится в заголовке, почему ребята Django решили реализовать объект request.POST с запросом (который, конечно же, в свою очередь, делает все неизменным?)

Я знаю, что вы можете его испортить, сделав копию данных сообщения

post = request.POST.copy()

но зачем это делать? Конечно, было бы проще просто позволить вещи быть изменчивыми в любом случае? Или он используется по какой-либо другой причине, которая может вызвать проблемы?

Ответ 1

Это немного тайна, не так ли? Несколько поверхностно правдоподобных теорий оказываются ошибочными в расследовании:

  • Чтобы объект POST не должен реализовывать методы мутации? Нет: объект POST принадлежит классу django.http.QueryDict, который реализует полный набор методов мутации, включая __setitem__, __delitem__, pop и clear. Он реализует неизменность, проверяя флаг, когда вы вызываете один из методов мутации. И когда вы вызываете метод copy, вы получаете другой экземпляр QueryDict с включенным флагом.

  • Для улучшения производительности? Нет: класс QueryDict не получает выгоды от производительности при отключении изменяемого флага.

  • Чтобы объект POST можно было использовать в качестве словарного ключа? Нет: QueryDict объекты не хешируются.

  • Итак, данные POST могут создаваться лениво (без чтения всего ответа), как заявлено здесь? Я не вижу никаких доказательств этого в коде: насколько я могу судить, весь ответ всегда читается, либо напрямую, либо через MultiPartParser для ответов multipart.

  • Чтобы защитить вас от ошибок программирования? Я видел, как это утверждалось, но я никогда не видел хорошего объяснения того, что такое эти ошибки, и как непреложность защищает вас от них.

В любом случае, POST не всегда неизменен: когда ответ multipart, тогда POST является изменяемым. Кажется, это кибош в большинстве теорий, о которых вы могли бы подумать. (Если это поведение не является надзором.)

В заключение, я не вижу в Django ясного логического обоснования для объекта POST, который должен быть неизменным для запросов multipart.

Ответ 2

Если запрос был результатом представления Django form, тогда разумно, чтобы POST был immutable, чтобы обеспечить целостность данных между формой подчинения и формой валидации. Однако, если запрос был не отправлен через представление Django form, то POST - mutable, поскольку проверка формы отсутствует.

Вы всегда можете сделать что-то вроде этого: (согласно @leo-the-manic comment)

#  .....
mutable = request.POST._mutable
request.POST._mutable = True
request.POST['some_data'] = 'test data'
request.POST._mutable = mutable
# ......

Ответ 3

Обновление

Гарет Рис был прав, что точки 1 и 3 в этом случае недействительны. Хотя я думаю, что пункты 2 и 4 все еще актуальны, поэтому я оставлю тезисы здесь.

(Я заметил, что объект request.POST как Pyramid (Pylon), так и Django - это некоторая форма MultiDict. Поэтому, возможно, это более распространенная практика, чем создание request.POST неизменяемых.)


Я не могу говорить за парней Django, хотя мне кажется, что это может быть из-за некоторых из этих причин:

  • Исполнение. неизменяемые объекты "быстрее" над изменчивыми, поскольку они позволяют существенно оптимизировать. Объект неизменный означает, что мы можем выделить для него пространство во время создания, а требования к пространству не изменяются. Из-за этого у него также есть такие вещи, как эффективность копирования и эффективность сравнения.Забастовкa > Изменить: это не относится к QueryDict, как указал Гарет Рис.
  • В случае request.POST кажется, что никакой активности на стороне сервера не нужно будет изменять данные запроса. И, следовательно, неизменяемые объекты более подходят, не говоря уже о том, что они обладают существенным преимуществом.
  • Неизменяемые объекты могут использоваться как клавиши dict, которые, я полагаю, могут быть очень полезны где-то в Django.. Изменить: моя ошибка, неизменяемая, прямо не подразумевает хеширование; хешируемые объекты, как правило, неизменяемы.
  • Когда вы проходите request.POST (особенно сторонние плагины и выходы), вы можете ожидать, что этот объект запроса от пользователя останется без изменений.

В какой-то мере эти причины также являются типичными ответами на "неизменяемые vs mutable"? вопрос. Я уверен, что в деле Django существует гораздо больше соображений дизайна, чем указано выше.

Ответ 4

Мне нравится, что он по умолчанию неизменен. Как указано, вы можете сделать его изменчивым, если вам нужно, но вы должны быть откровенным. Это похоже на "Я знаю, что могу сделать свою форму отладкой кошмара, но я знаю, что я делаю сейчас".

Ответ 5

Я нашел это в комментарии по ответу стека fooobar.com/info/77384/...

И он должен быть неизменным, чтобы его можно было построить лениво. Копия заставляет получать все данные POST. Пока копия не может быть выбрана. Кроме того, для многопоточного WSGI-сервера для работы достаточно хорошо, полезно, если это является неизменным