2015-04-17 17 views
6

Ich habe eine Django-Ansicht, die einen Abfrageparameter verwendet, um eine Inhaltsfilterung durchzuführen. Etwas wie folgt aus:Testen von Anforderungsparametern in Django ("+" verhält sich anders)

/page/?filter=one+and+two 
/page/?filter=one,or,two 

ich bemerkt habe, dass Django die + in einen Raum konvertiert (request.GET.get('filter') kehrt one and two), und ich bin mit dem OKAY. Ich muss nur die split() Funktion anpassen, die ich in der Ansicht entsprechend verwende.

Aber ...

Wenn ich versuche, diese Ansicht zu testen, und ich rufe:

from django.test import Client 
client = Client() 
client.get('/page/', {'filter': 'one+and+two'}) 

request.GET.get('filter') kehrt one+and+two: mit Pluszeichen und keine Leerzeichen. Warum ist das?

Ich würde gerne denken, dass Client().get() imitiert das Verhalten des Browsers, so was ich gerne verstehen würde, warum Anruf client.get('/page/', {'filter': 'one+and+two'}) ist nicht wie Surfen zu /page/?filter=one+and+two. Zu Testzwecken sollte es meiner Meinung nach gleich sein, und in beiden Fällen sollte die Ansicht einen konsistenten Wert für Filter erhalten: sei es mit + oder mit Leerzeichen.

Was ich nicht verstehe ist, warum es zwei verschiedene Verhaltensweisen gibt.

Antwort

9

Die Pluszeichen in einer Abfragezeichenfolge sind die normale und korrekte Codierung für Leerzeichen. Dies ist ein historisches Artefakt; Die form value encoding for URLs unterscheidet sich nur geringfügig von der Codierung anderer Elemente in der URL.

Django ist verantwortlich für die Entschlüsselung der Abfrage-String zurück zu Schlüssel-Wert-Paare; Diese Decodierung umfasst das Decodieren der URL-Prozentcodierung, wobei ein + in ein Leerzeichen decodiert wird.

Wenn Sie den Test-Client verwenden, übergeben Sie in uncodierte Daten, so würden Sie verwenden:

client.get('/page/', {'filter': 'one and two'}) 

Dies wird dann zu einem Query-String codiert für Sie, und anschließend wieder decodiert werden, wenn Sie versuchen, Zugriff auf die Parameter

+0

Ok, also muss ich 'client.get ('/ page /', {'filter': 'eins zwei drei'})' in meinen Tests verwenden, so wie ich es gemacht habe. Meine Sorge war, dass dies nicht konsistent erscheint (wenn "Client" einen Browser nachahmt). Es sollte 'client.get ('/ page /', {'filter': 'eins + zwei + drei'})' meiner Meinung nach sein. Aber ich denke, so wird 'Client' entworfen. Danke trotzdem! – eillarra

+1

@Eeillarra: Es ist konsistent mit der Darstellung der Daten in einer Django-Ansicht. Wie die Daten herumgereicht werden (kodiert in einer Query-Zeichenfolge), spielt dort keine Rolle. –

2

Dies liegt daran, dass der Testclient (eigentlich RequestFactory) django.utils.http.urlencode für Ihre Daten ausführt, was zu filter=one%2Band%2Btwo führt. Ähnlich, wenn Sie {'filter': 'one and two'} verwenden würden, würde es in filter=one%20and%20two umgewandelt werden und würde mit Leerzeichen in Ihre Ansicht kommen.

Wenn Sie unbedingt die Pluspunkte in Ihrer Abfragezeichenfolge haben müssen, glaube ich, dass es möglich sein kann, die Abfragezeichenfolge mit etwas wie: client.get('/page/', QUERY_STRING='filter=one+and+two') manuell zu überschreiben, aber das scheint meiner Meinung nach unnötig und hässlich.

+0

Das einzige, was ich tun möchte, ist, meine Tests wie eine "echte" Anfrage zu schreiben. Ich könnte 'client.get ('/ page /', {'filter': 'eins zwei drei'})' im Test schreiben, und es wird bestanden, weil die Ansicht in diesem Fall 'eins zwei drei' erhält. Aber es scheint nicht logisch. – eillarra

+0

@Eeillarra, Pluszeichen ist Sonderfall in Abfragezeichenfolge, bedeutet Leerzeichen. Deshalb führt Django die Konvertierung durch. Siehe: http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 und http: // stackoverflow.com/questions/1005676/urls-and-plus-signs Also ich denke, es ist in Ordnung, nur 'eins zwei drei' in Testfällen zu verwenden. – ZZY

+0

'django.utils.http.urlencode()' erzeugt 'filter = eins + und + zwei', weil das die richtige Kodierung für Leerzeichen in einem Abfrageparameter ist. –

Verwandte Themen