2010-12-18 13 views
12

Ich schreibe eine Django-Anwendung mit einer URL wie 'http: // localhost/entity/id /? Overlay = andere_id'. Dabei ist id der Primärschlüssel der bestimmten Entität, und Overlay ist ein optionaler Abfrageparameter für eine zweite Entität, die in der Anzeige überlagert werden soll. Der Benutzer kann eine Entität immer nur aktualisieren, wenn er Objekte über ein Overlay anzeigt. Beim POSTing nach/update/id möchte ich zurück zu/entity/id umleiten, aber ich möchte meinen Abfrageparameter während der Weiterleitung nicht verlieren, da die Änderung in der Ansicht störend wäre.Django Redirect mit reverse() zu einer URL, die auf Abfragezeichenfolgen

Zum Beispiel habe ich in meinem url.py folgende bekam:

... 
(r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update'), 
(r'^entity/(?P<id>.+)/$', 'view'), 
... 

Da overlay_id ist erforderlich, wenn die Aktualisierung, es ist Teil der URL ist, kein Abfrageparameter. In der Django-Ansicht möchte ich nach einem erfolgreichen POST umleiten und reverse() verwenden, um zu vermeiden, dass URLs in meinem Python-Code referenziert werden. Die allgemeine Idee ist:

return HttpResponseRedirect(
    reverse('views.view', 
    kwargs={ 
     'id': id, 
    }, 
) 
) 

Aber wie übergebe ich meine Abfrageparameter umgekehrt?

Danke, Craig

Antwort

5

Sie können nicht überprüfen, nur eine für overlay_id und fügen Sie Ihre URL?

redirect_url = reverse(...) 
extra_params = '?overlay=%s' % overlay_id if overlay_id else '' 
full_redirect_url = '%s%s' % (redirect_url, extra_params) 
return HttpResponseRedirect(full_redirect_url) 
+0

Ja, das habe ich beim Zähneputzen vor einer Sekunde bemerkt. Manchmal wünschte ich, Python hätte Typensignaturen, da dies offensichtlich gewesen wäre, wenn reverse() deklariert wurde, um eine Zeichenkette zurückzugeben. Vielen Dank. –

+0

Normalerweise bekomme ich diese ah ha Momente in der Dusche am nächsten Morgen. Sie könnten feststellen, dass pdb (oder ipdb) in Fällen hilft, in denen Sie nach Typ-Signaturen suchen. Versuchen Sie, 'import pdb zu werfen; pdb.set_trace() 'in Ihren Code einige Zeit. http://docs.python.org/library/pdb.html – istruble

4

Abfragezeichenfolgenargumente sollten ordnungsgemäß maskiert und nicht einfach verkettet werden!

Das Erstellen einer URL mit Abfragezeichenfolge nach Zeichenfolgenverkettung ist ebenso eine schlechte Idee wie das Erstellen von SQL-Abfragen durch Zeichenfolgenverkettung. Es ist kompliziert, unelegant und besonders gefährlich mit einem vom Benutzer bereitgestellten (nicht vertrauenswürdigen) Eingang. Leider bietet Django keine einfache Möglichkeit, Abfrageparameter an die reverse Funktion zu übergeben.

Python-Standard urllib bietet jedoch die gewünschte Abfragezeichenfolgencodierungsfunktionalität.

In meinem application Ich habe eine Hilfsfunktion wie folgt erstellt:

def url_with_querystring(path, **kwargs): 
    return path + '?' + urllib.urlencode(kwargs) 

Dann habe ich es in der Ansicht wie folgt aufrufen:

quick_add_order_url = url_with_querystring(reverse(order_add), 
    responsible=employee.id, scheduled_for=datetime.date.today(), 
    subject='hello world!') 
# http://localhost/myapp/order/add/?responsible=5& 
#  scheduled_for=2011-03-17&subject=hello+world%21 

Bitte beachten Sie die richtige Codierung von Sonderzeichen wie Leerzeichen und Ausrufezeichen!

+0

Es gibt keine Notwendigkeit, sich die Mühe der URL-Codierung der Abfrage-String-Parameter selbst zu gehen. HTTPResponseRedirect wird es für Sie tun. –

+2

@Declan Shanaghy HTTPResponseRedirect bietet keine Funktionalität für die Abfragezeichenfolgen-Assemblierung (django-Dokumentation: "Der Konstruktor benötigt ein einzelnes Argument - den Pfad zum Weiterleiten an."), Also müssen Sie es selbst tun. Aber nicht mit einer einfachen String-Verkettung wie von istruble vorgeschlagen - dies funktioniert nicht bei Werten, die Sonderzeichen oder Leerzeichen enthalten. – geekQ

17

Sie können eine Django QueryDict Objekt verwenden:

from django.http import QueryDict 

# from scratch 
qdict = QueryDict('',mutable=True) 

# starting with our existing query params to pass along 
qdict = request.GET.copy() 

# put in new values via regular dict 
qdict.update({'foo':'bar'}) 

# put it together 
full_url = reversed_url + '?' + qdict.urlencode() 

Und natürlich können Sie eine bequeme Methode, um sie ähnlich wie die vorherige Antwort schreiben.

3

Sie sollten die URL-Zeichenfolge nicht selbst generieren. Angesichts Ihrer URLs.py können Sie wie so umkehren verwenden:

from django.core.urlresolvers import reverse 
print reverse('view_function_name', kwargs={"id":"id_value", "overlay_id": "overlay_id_value"}) 

# or to pass view function arguments as an array: 
print reverse('view_function_name', args=("id_value","overlay_id_value",)) 

Wenn Sie named url patterns verwenden, die Ihre Ansicht groß sind Funktionen von URL-Kennungen zum Trennen:

# urls.py 
... 
(r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update', name="update_foo"), 
... 

Verwendung wie so umkehren:

print reverse("update_foo", kwargs={"id":"id_value", "overlay_id": "overlay_id_value"}) 
+0

Es gibt _no_way_, dass dort zwischen einfachen Anführungszeichen und doppelten Anführungszeichen unterschieden wird. –

+0

Alles außer meiner Erfahrung an diesem Tag des 27. März möchte ich meine Antwort für jeden Kommentar bearbeiten. Kann jemand anderes bestätigen? – dbro

+0

Es ist möglich, dass Sie in einer Instanz das "r" (oder "r" :) am Anfang der Zeichenfolge vergessen haben. Nicht in diesen Beispielen, aber in anderen, wo Sie Dinge wie \ d verwenden, wird das Fehlen des "r" Python die \ d (und andere) als Sonderzeichen interpretieren, anstatt sie für die RE-Engine zu verlassen . Das ist die beste Schätzung, die ich mir vorstellen kann. Wenn Sie die Anweisung, die nicht funktioniert hat, finden - bevor Sie sie beheben, können wir sie analysieren. –

Verwandte Themen