111 votes

django - pourquoi l'objet request.POST est-il immuable ?

Comme le demande le titre, pourquoi les gars de Django ont-ils décidé d'implémenter l'objet request.POST avec un querydict (ce qui, bien sûr, rend le tout immuable) ?

Je sais que tu peux mutifier en faisant une copie des données postales

post = request.POST.copy()

mais pourquoi faire cela ? Il serait sûrement plus simple de permettre à la chose d'être mutable de toute façon ? Ou bien est-il utilisé pour une autre raison qui pourrait poser problème ?

1 votes

Pourquoi voulez-vous qu'il soit mutable ? Vous pouvez prendre les données qui s'y trouvent et les utiliser/modifier dans votre vue. En y ajoutant des données, vous pouvez donner l'impression que request.POST a été soumis avec plus de données qu'il ne l'a été en réalité.

11 votes

Ce n'est pas que je veulent qu'il soit mutable. Pas plus que, disons, je ne voudrais que la crème glacée soit froide. Dans le cas de la crème glacée cependant, si c'est n'est pas froid, il fond et ensuite tu te fais gronder pour avoir fait un gros gâchis. Mais avec l'objet request.POST... Je veux dire, si je dois bousiller mon code, je vais le bousiller. Je ne savais pas qu'il y avait une endémie de développeurs ajoutant des données aux objets POST et causant des problèmes, donc ça semble être une chose étrange à cibler pour "réparer".

0 votes

Bonne question ; je n'y ai jamais vraiment pensé.

133voto

Gareth Rees Points 31350

C'est un peu un mystère, n'est-ce pas ? Plusieurs théories superficiellement plausibles s'avèrent fausses après enquête :

  1. Pour que le POST n'a pas besoin d'implémenter des méthodes de mutation ? Non : l'objet POST appartient à l'objet django.http.QueryDict classe qui met en œuvre un ensemble complet de méthodes de mutation, dont les suivantes __setitem__ , __delitem__ , pop y clear . Il implémente l'immuabilité en vérifiant un drapeau lorsque vous appelez l'une des méthodes de mutation. Et lorsque vous appelez la méthode copy vous obtenez une autre QueryDict avec le drapeau mutable activé.

  2. Pour l'amélioration des performances ? Non : le QueryDict ne bénéficie d'aucun avantage en termes de performances lorsque le drapeau mutable est désactivé.

  3. Pour que le POST peut être utilisé comme clé de dictionnaire ? Non : QueryDict ne sont pas hachables.

  4. Pour que le POST peuvent être construites paresseusement (sans s'engager à lire l'ensemble de la réponse), comme revendiqué ici ? Je ne vois aucune trace de cela dans le code : pour autant que je sache, l'ensemble de la réponse est toujours lu, soit directement ou via MultiPartParser para multipart réponses.

  5. Pour vous protéger contre les erreurs de programmation ? J'ai vu cette affirmation, mais je n'ai jamais vu une bonne explication de ce que sont ces erreurs, et comment l'immuabilité vous protège contre elles.

En tout cas, POST est pas toujours immuable lorsque la réponse est multipart alors POST est mutable. Cela semble mettre le holà à la plupart des théories auxquelles vous pourriez penser. (A moins que ce comportement ne soit un oubli).

En résumé, Je ne vois pas de raison claire dans Django pour le POST pour qu'il soit immuable pour les non multipart demandes.

0 votes

J'ai remarqué des tonnes d'irrégularités comme celle-ci dans Django. Ça a dû avoir un sens pour quelqu'un à un moment donné, cependant.

2 votes

J'ai trouvé ça dans une autre réponse de Stack : "Et il doit être immuable pour qu'il puisse être construit de manière paresseuse. La copie oblige à récupérer toutes les données POST. Jusqu'à la copie, elles peuvent ne pas être toutes récupérées. De plus, pour qu'un serveur WSGI multithread fonctionne raisonnablement bien, il est utile qu'il soit immuable".

0 votes

Ah, désolé, j'ai raté ça. Je n'ai lu que la question et les deux premiers points de votre message. J'essayais juste d'être gentil et de suivre les informations que j'avais trouvées ailleurs. Peut-être que le chargement était paresseux avant, mais qu'il ne l'est plus maintenant, et que le QueryDict est un code qui doit être remplacé Je ne sais pas.

84voto

Val Neekman Points 1238

Si la demande est le résultat d'une requête Django form soumission, alors il est raisonnable pour le POST étant immutable pour garantir l'intégrité des données entre le formulaire soumission et la forme validation . Toutefois, si la demande était no envoyé via un système Django form la soumission, alors le POST est mutable car il n'y a pas de validation du formulaire.

Vous pouvez toujours faire quelque chose comme ceci : (comme pour Commentaire de @leo-the-manic )

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

3 votes

@JoshK : Je suppose que le commentateur voulait rendre POST mutable, et l'extrait de code dans cette réponse l'a aidé.

0 votes

Vous pouvez ajouter de nouvelles clés et valeurs, mais vous ne pouvez pas modifier les données existantes.

0 votes

Joli. Et je suis sûr que celui qui utilise ce code sait ce qu'il ou elle fait.

5voto

Kay Zhu Points 9703

Mise à jour :

Gareth Rees avait raison de dire que les points 1 et 3 n'étaient pas valables dans ce cas. Cependant, je pense que les points 2 et 4 sont toujours valables, et je vais donc laisser ces thèses ici.

(J'ai remarqué que le request.POST de Pyramid(Pylon) et de Django est une forme de MultiDict . Donc peut-être que c'est une pratique plus courante que de faire request.POST immuable).


Je ne peux pas parler pour les gars de Django, mais il me semble que cela pourrait être dû à certaines de ces raisons :

  1. Performances . les objets immuables sont plus "rapides" que les objets mutables dans la mesure où ils permettent des optimisations substantielles. Un objet est immuable signifie que nous pouvons lui allouer de l'espace à date de création et les besoins en espace ne changent pas. Il a aussi des avantages comme l'efficacité de la copie et de la comparaison. Editar : ce n'est pas le cas pour QueryDict comme l'a souligné Gareth Rees.
  2. Dans le cas de request.POST il semble qu'aucune activité du côté serveur ne doive modifier l'adresse de l'utilisateur. de la demande données. Les objets immuables sont donc plus adaptés, sans compter qu'ils présentent un avantage substantiel en termes de performances.
  3. Les objets immuables peuvent être utilisés comme dict clés, que je Supposons que pourrait être très utile quelque part dans Django Editar : mon erreur, immuable n'implique pas directement hachable ; hachable Cependant, les objets sont généralement immuable également.
  4. Quand vous passez autour request.POST (notamment à des plugins tiers et out), vous pouvez vous attendre à ce que cet objet de requête de l'utilisateur reste inchangé.

D'une certaine manière, ces raisons sont également des réponses génériques à la question "immuable ou mutable". Je suis certain qu'il y a beaucoup plus de considérations de conception que celles mentionnées ci-dessus dans le cas de Django.

1 votes

Le dernier cas est vraiment important. Il s'agit vraiment de la sécurité. C'est pourquoi Django fournit sessions qui est un moyen rapide d'obtenir et de modifier les données entre les états.

2 votes

Votre point (1) ne peut pas être la réponse dans ce cas, parce que POST est un QueryDict objet et ces objets n'ont aucun avantage en termes de performances à être immuables. Et votre point (3) ne peut pas être la réponse, parce que QueryDict ne sont pas hachables, et ne peuvent donc pas être utilisés comme clés de dictionnaire.

0 votes

@GarethRees Merci de les avoir signalés. En effet, j'avais tort. J'ai mis à jour ma réponse pour les corriger. J'aurais dû prêter plus d'attention à QueryDict avant de répondre.

4voto

pawelmech Points 375

J'aime qu'il soit immuable par défaut. Comme indiqué, vous pouvez le rendre mutable si vous en avez besoin, mais vous devez être explicite à ce sujet. C'est comme "Je sais que je peux faire du débogage de mon formulaire un cauchemar, mais je sais ce que je fais maintenant".

2voto

Seaux Points 1546

J'ai trouvé ceci dans un commentaire sur Stack Answer https://stackoverflow.com/a/2339963

Et il doit être immuable afin de pouvoir être construit paresseusement. La copie oblige à récupérer toutes les données du POST. Jusqu'à la copie, elles peuvent ne pas être toutes récupérées. De plus, pour qu'un serveur WSGI multithread fonctionne raisonnablement bien, il est utile qu'il soit immuable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X