2012-09-26 13 views
79

Come il titolo si chiede, perché i ragazzi Django decidono di implementare l'oggetto request.POST con un QueryDict (che, ovviamente, a sua volta, rende il tutto immutabile?)django - perché la request.POST è immutabile?

So che è possibile mutify facendo una copia dei dati del post

post = request.POST.copy() 

ma perché farlo? Sicuramente sarebbe più semplice permettere che la cosa fosse mutabile comunque? Oppure viene utilizzato anche per altri motivi che potrebbero causare problemi?

+1

Perché vuoi che sia mutabile? Puoi prendere i dati da esso e usarli/modificarli nella tua vista. Aggiungendo i dati ad esso, è possibile creare l'impressione che 'request.POST' sia stato inviato con più dati di quanti ne siano stati effettivamente. –

+7

Non è che * voglio * che sia mutabile. Non più di, diciamo, vorrei che il gelato fosse freddo. Nel caso del gelato però, se * non è * freddo si scioglie e poi ti rimproveri per fare un gran casino. Ma con la request.POST oggetto ... Voglio dire, se ho intenzione di rovinare il mio codice, ho intenzione di rovinare tutto. Non ero a conoscenza dell'esistenza di un endemico di sviluppatori che aggiungevano dati agli oggetti POST e Causing Problems, quindi sembra una cosa strana mirare a "riparare". – bharal

+0

Bella domanda; mai pensato davvero –

risposta

107

È un po 'un mistero, non è vero?Diverse teorie superficialmente plausibili rivelarsi sbagliato sulle indagini:

  1. modo che l'oggetto POST non deve implementare i metodi di mutazione? No: l'oggetto POST appartiene allo django.http.QueryDict class, che implementa un set completo di metodi di mutazione tra cui __setitem__, __delitem__, pop e clear. Implementa l'immutabilità controllando un flag quando si chiama uno dei metodi di mutazione. E quando chiami il metodo copy ottieni un'altra istanza QueryDict con il flag mutabile attivato.

  2. Per il miglioramento delle prestazioni? No: la classe QueryDict non offre alcun vantaggio in termini di prestazioni quando il flag mutabile è disattivato.

  3. In modo che l'oggetto POST possa essere utilizzato come chiave del dizionario? No: gli oggetti QueryDict non sono lavabili.

  4. In modo che i dati POST possano essere costruiti pigramente (senza impegnarsi a leggere l'intera risposta), as claimed here? Non vedo alcuna prova di ciò nel codice: per quanto posso dire, l'intera risposta viene sempre letta, sia directly, sia tramite MultiPartParser per le risposte multipart.

  5. Per proteggersi dagli errori di programmazione? L'ho visto affermare, ma non ho mai visto una buona spiegazione di cosa siano questi errori e di come l'immutabilità ti protegga contro di loro.

In ogni caso, è POSTnon sempre immutabile: quando la risposta è multipart, quindi POST è mutevole. Questo sembra mettere il kibosh sulla maggior parte delle teorie che potreste pensare. (A meno che questo comportamento è una svista.)

In sintesi, vedo alcuna chiara spiegazione razionale in Django per l'oggetto POST essere immutabili per i non multipart richieste.

+0

Ho notato tonnellate di spigoli come questo in Django. Deve avere un senso per qualcuno ad un certo punto, però. –

+2

Ho trovato questo in un'altra risposta Stack: "E deve essere immutabile in modo che possa essere costruito pigramente.La copia impone di ottenere tutti i dati POST. Fino a quando la copia, non può essere recuperata. Inoltre, per un multi-threaded Il server WSGI funziona ragionevolmente bene, è utile se questo è immutabile " – Seaux

+0

@Seaux: vedi il mio punto # 4. –

5

Aggiornamento:

Gareth Rees era giusto che il punto 1 & 3 non erano validi in questo caso. Anche se penso che i punti 2 e 4 siano ancora validi, quindi lascerò qui le tesi.

(ho notato che l'oggetto sia della piramide (pilone) e Django request.POST è una qualche forma di MultiDict. Quindi, forse, è una pratica più comune di fare request.POST immutabili.)


posso 't parlano per i ragazzi Django, anche se mi sembra che poteva a causa di alcuni di questi motivi:

  1. Performence. Gli oggetti immutabili sono "più veloci" rispetto a quelli mutabili, in quanto consentono sostanziali ottimizzazioni. Un oggetto è immutabile significa che è possibile allocare lo spazio per il tempo di creazione ei requisiti di spazio non cambiano. Ha anche cose come efficienza di copia e efficienza di confronto a causa di esso. Modifica: questo non è il caso di QueryDict come ha sottolineato Gareth Rees.
  2. Nel caso di request.POST, sembra che nessuna attività sul lato server debba modificare i dati della richiesta . E quindi gli oggetti immutabili sono più adatti, per non dire che hanno un vantaggio sostanziale in termini di prestazioni.
  3. oggetti immutabili possono essere utilizzati come dict chiavi, che io suppongo potrebbe essere molto utile da qualche parte in Django .. Modifica: il mio errore, immutabile non implica direttamente hashable; Gli oggetti lavabili, tuttavia, sono in genere immutabili.
  4. Quando si passa request.POST (in particolare verso plug-in di terze parti e fuori), è possibile aspettarsi che questo oggetto richiesta dall'utente rimanga invariato.

In qualche modo queste ragioni sono anche risposte generiche a "immutabile vs mutabile?" domanda. Sono certo che ci sono molte più considerazioni sul design che sopra nel caso Django.

+1

L'ultimo caso è davvero importante. Si tratta davvero di sicurezza. Questo è il motivo per cui Django fornisce 'sessioni', che è un modo breve di ottenere e modificare i dati tra stati. – CppLearner

+2

Il tuo punto (1) non può essere la risposta in questo caso, perché 'POST' è un oggetto [' QueryDict'] (https://github.com/django/django/blob/master/django/http/__init__ .py # L371), e questi oggetti non ottengono benefici dalle prestazioni immutabili. E il tuo punto (3) non può essere la risposta, perché gli oggetti 'QueryDict' non sono lavabili, e quindi non possono essere usati come chiavi del dizionario. –

+0

@GarethRees Grazie per aver indicato questi. Anzi, ho sbagliato. Ho aggiornato la mia risposta per correggerli. Avrei dovuto prestare maggiore attenzione a 'QueryDict' prima che io rispondessi. –

61

Se la richiesta è il risultato di una trasmissione Django form, allora è ragionevole per POST essere immutable per assicurare l'integrità dei dati tra forma presentazione e la forma convalida. Tuttavia, se la richiesta è stata non inviati tramite una sottomissione Django form, poi POST è mutable in quanto non v'è alcuna validazione dei form.

si può sempre fare qualcosa di simile: (come da @leo-the-manic's comment)

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

@JoshK: Immagino che il commentatore volesse rendere mutabile il POST, e il frammento di codice in questa risposta ha aiutato. – ShreevatsaR

+0

È possibile aggiungere una nuova chiave, valore ma non è possibile modificare i dati esistenti. –

2

Ho trovato questo in un commento su Stack Risposta https://stackoverflow.com/a/2339963

e deve essere immutabile, in modo che possa essere costruito pigramente. La copia impone di ottenere tutti i dati POST. Fino alla copia, potrebbe non essere stata scaricata.Inoltre, per un server WSGI multi-thread per funzionare ragionevolmente bene, è utile se questo è immutabile

3

Mi piace che sia immutabile per impostazione predefinita. Come indicato, è possibile renderlo mutevole se necessario, ma è necessario essere espliciti al riguardo. È come se "so che posso rendere il mio modulo il debug di un incubo, ma so cosa sto facendo ora".

Problemi correlati