django - request.POST nesnesi neden değişmez?


109

Başlığın sorduğu gibi, Django adamları neden request.POST nesnesini bir sorgudict ile uygulamaya karar verdiler (ki bu da tabii ki her şeyi değişmez kılıyor?)

Gönderi verilerinin bir kopyasını oluşturarak onu değiştirebileceğinizi biliyorum

post = request.POST.copy()

ama bunu neden yapıyorsun? Her halükarda bir şeyin değiştirilebilir olmasına izin vermek kesinlikle daha kolay olurdu? Yoksa soruna neden olabilecek başka bir nedenle mi kullanılıyor?


1
Neden değiştirilebilir olmasını istiyorsunuz? Verileri ondan alabilir ve kendi görünümünüzde kullanabilir / değiştirebilirsiniz. Buna veri ekleyerek, request.POSTgerçekte olduğundan daha fazla veriyle gönderilen gösterimi oluşturabilirsiniz .
Simeon Visser

11
Ben değil mi istiyorum o değişken olması. Diyelim ki, dondurmanın soğuk olmasını isterdim. Dondurma söz konusu olduğunda, soğuk değilse erir ve sonra büyük bir karışıklık yarattığınız için azarlanırsınız. Ama request.POST nesnesi ile ... Yani, eğer kodumu bozacaksam, onu alt üst edeceğim. Geliştiricilerin POST nesnelerine veri ekleyip Sorunlara Neden Olduğunun farkında değildim, bu nedenle "düzeltmeyi" hedeflemek garip bir şey gibi görünüyor.
bharal

Güzel soru; gerçekten hiç düşünmedim.
Burhan Khalid

1
Bu benim için ara sıra ortaya çıktı çünkü müşterim bazen JSON verileri (değiştirilebilir) ve bazen URL Formu Kodlanmış (değiştirilemez) mesajlar gönderdi.
owenfi

2
İngilizce konuşmayanlar için "mutify" bir kelime değildir - doğru ifade "onu değiştirebilirsin" veya "onu değiştirebilirsin" dir. Ayrıca geliştiricilerin cinsiyetini belirlemenize gerek yoktur - "adamlar" yerine "Django takımı" veya "çekirdek geliştiriciler" kullanabilirsiniz.
alexmuller

Yanıtlar:


131

Biraz muamma, değil mi? Yüzeysel olarak makul olan birkaç teori, soruşturma sırasında yanlış çıktı:

  1. Böylece POSTnesnenin mutasyon yöntemlerini uygulaması gerekmiyor mu? No: POSTNesne aittir django.http.QueryDictsınıfın mutasyon yöntemleri tam set dahil uygular, __setitem__, __delitem__, popve clear. Mutasyon yöntemlerinden birini çağırdığınızda bir bayrağı kontrol ederek değişmezliği uygular. Ve copyyöntemi çağırdığınızda QueryDict, değiştirilebilir bayrağı açık olan başka bir örnek alırsınız .

  2. Performans iyileştirmesi için mi? Hayır: QueryDictSınıf, değiştirilebilir bayrak kapatıldığında performans avantajı sağlamaz.

  3. Böylece POSTnesne bir sözlük anahtarı olarak kullanılabilir mi? Hayır: QueryDictnesnelere hashing uygulanamaz.

  4. Böylece, burada iddia edildiği gibiPOST veriler tembel bir şekilde (tüm yanıtı okumayı taahhüt etmeden) oluşturulabilir mi? Ben kodunda bu hiçbir kanıt bkz: bildiğim kadarıyla söyleyebilirim, yanıtının tüm daima ya okunduğunda doğrudan veya üzeri için yanıtlar.MultiPartParsermultipart

  5. Sizi programlama hatalarına karşı korumak için mi? Bunun iddia edildiğini gördüm, ancak bu hataların ne olduğuna ve değişmezliğin sizi bunlara karşı nasıl koruduğuna dair iyi bir açıklama görmedim.

Her durumda, POSTbir zaman değişmez değildir : tepkisi olduğunda multipart, o zaman POSTdeğişkendir. Bu, aklınıza gelebilecek çoğu teoriye kibosh koyuyor gibi görünüyor. (Bu davranış bir gözetim olmadığı sürece.)

Özetle, ben net gerekçesini görebilirsiniz için Django POSTolmayan için değişmez olduğu nesne multipartistekleri.


Django'da bunun gibi tonlarca pürüzlülük fark ettim. Yine de bir noktada birine mantıklı gelmiş olmalı.
Dan Passaro

2
Bunu başka bir Yığın yanıtında buldum: "Ve tembel olarak oluşturulabilmesi için değişmez olması gerekir. Kopya, tüm POST verilerini almaya zorlar. Kopyaya kadar hepsi alınamayabilir. Dahası, çok iş parçacıklı bir WSGI için sunucunun oldukça iyi çalışması, bu değişmez olması
yararlıdır

12
@Seaux, yorum yapmak istediğinizde SO cevaplarını tembelce okumamalısınız. ;-)
Chris Wesseling

3
@ChrisWesseling Orada ne yaptığını görüyorum
Seaux

2
Daha da iyisi, django test istemcisine dava açtığımda sorgu diktesi değişebilir.
user1158559

82

Talep bir Django formgönderiminin sonucuysa, POST'un form gönderimi ile form doğrulaması arasındakiimmutable verilerin bütünlüğünü sağlaması mantıklıdır . İstek olsaydı Ancak, değil bir Django yoluyla gönderilen sunulması, ardından POST hiçbir form doğrulama olmadığı için.formmutable

Her zaman böyle bir şey yapabilirsiniz: ( @ leo-the-manic'in yorumuna göre )

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

3
@JoshK: Yorumcu POST'u değiştirilebilir yapmak istedi ve bu yanıttaki kod parçacığı yardımcı oldu.
ShreevatsaR

Yeni anahtar, değer ekleyebilirsiniz ancak mevcut verileri değiştiremezsiniz.
Vamsidhar Muğla

Güzel. Ve eminim bu kodu kullanan kişi ne yaptığını biliyordur.
John Pang

@VamsidharMuggulla Hem ekleme hem de değiştirme mümkündür. Silmeye bile izin verilir.
Antony Hatchkins

5

Güncelleme :

Gareth Rees, bu durumda 1 ve 3'ün geçerli olmadığı konusunda haklıydı. 2. ve 4. noktaların hala geçerli olduğunu düşünmeme rağmen, bu nedenle tezleri burada bırakacağım.

( request.POSTHem Pyramid (Pylon) hem de Django'nun nesnesinin bir tür olduğunu fark ettim MultiDict. Bu yüzden belki de request.POSTdeğişmez yapmaktan daha yaygın bir uygulamadır .)


Django adamları adına konuşamam, bana öyle geliyor ki, aşağıdaki nedenlerden bazıları:

  1. Performans . immutable nesneler, önemli optimizasyonlara izin verdiklerinden, değiştirilebilir olanlara göre "daha hızlıdır". Bir nesnenin değişmez olması, yaratılış zamanında ona yer ayırabileceğimiz ve alan gereksinimlerinin değişmediği anlamına gelir. Aynı zamanda kopya verimliliği ve karşılaştırma verimliliği gibi şeylere de sahiptir. Düzenleme :QueryDictGareth Rees'in işaretettiğigibidurum böyle değil.
  2. Bu durumda request.POST, sunucu tarafında hiçbir faaliyetin talebin verilerini değiştirmesi gerekmiyor gibi görünüyor . Ve bu nedenle değişmez nesneler daha uygundur, önemli performans avantajlarına sahip olduklarından bahsetmeye bile gerek yok.
  3. Değişken olmayan objeler olarak kullanılabilir dictAnahtarlar, herhalde Django .. çok yararlı bir yerde olabilir Edit : Benim hatam, değişmez doğrudan anlamına gelmez hashable ; bununla birlikte, hashable nesneler de tipik olarak değişmezdir .
  4. Etrafta dolaşırken request.POST(özellikle üçüncü taraf eklentilere ve dışarıya), kullanıcıdan gelen bu istek nesnesinin değişmeden kalmasını bekleyebilirsiniz.

Bir şekilde bu nedenler aynı zamanda "değişmez mi, değişmez mi?" Sorusuna genel yanıtlardır. soru. Eminim, Django durumunda yukarıdakinden çok daha fazla tasarım düşüncesi vardır.


1
Son vaka gerçekten önemli. Gerçekten güvenlikle ilgili. Bu nedenle Django, sessionsdurumlar arasında verileri almak ve değiştirmek için kısa ömürlü bir yol sağlar.
CppLearner

2
Bu durumda noktanız (1) cevap olamaz, çünkü POSTbir QueryDictnesnedir ve bu nesneler değişmez olmanın performans açısından hiçbir faydası olmaz. Ve amacınız (3) cevap olamaz, çünkü QueryDictnesneler karma hale getirilebilir değildir ve bu nedenle sözlük anahtarları olarak kullanılamaz.
Gareth Rees

@GarethRees Bunları işaret ettiğiniz için teşekkürler. Hakikaten yanılmışım. Bunları düzeltmek için cevabımı güncelledim. QueryDictCevap vermeden önce daha çok dikkat etmeliydim .
KZ

7
@CppLearner Güvenlik noktası tartışmalı görünüyor, örneğinrequests.POST._mutable = True; requests.POST['foo'] = 'bar'; request.POST._mutable = False
Dan Passaro

4

Varsayılan olarak değişmez olmasını seviyorum. Belirtildiği gibi, gerekirse onu değiştirilebilir hale getirebilirsiniz, ancak bu konuda açık olmalısınız. Sanki 'Formumu bir kabustan hata ayıklayarak yapabileceğimi biliyorum ama şimdi ne yaptığımı biliyorum.'


2

Bunu Yığın Cevabı https://stackoverflow.com/a/2339963'teki bir yorumda buldum

Ve tembel olarak inşa edilebilmesi için değişmez olması gerekir. Kopyalama, tüm POST verilerini almaya zorlar. Kopyaya kadar hepsi alınmayabilir. Ayrıca, çok iş parçacıklı bir WSGI sunucusunun makul derecede iyi çalışması için, bu değişmez ise yararlıdır


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.