2010-12-18 13 views
12

Estoy escribiendo una aplicación Django con una URL como 'http: // localhost/entidad/id/superposición = other_id'. Donde id es la clave primaria de la entidad particular y la superposición es un parámetro de consulta opcional para una segunda entidad que se superpone en la pantalla. El usuario solo puede actualizar una entidad cuando visualiza objetos a través de una superposición. Cuando se realiza la transferencia a/update/id, quiero volver a dirigirme a/entity/id, pero no quiero perder mi parámetro de consulta durante el redireccionamiento, ya que el cambio en la vista sería discordante.Django redirigir usando inversa() a una dirección URL que se basa en las cadenas de consulta

Por ejemplo, Tengo el siguiente en mi url.py:

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

Debido a que se requiere overlay_id cuando se actualiza, es parte de la URL, no es un parámetro de consulta. En la vista django quiero redirigir después de una POST exitosa y usar reverse() para evitar hacer referencia a las URL en mi código python. La idea general es:

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

Pero, ¿cómo puedo pasar el parámetro de mi consulta a la inversa?

Gracias, Craig

Respuesta

5

¿No puedes comprobar si existe una overlay_id y añadirlo a su 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

Sí, me di cuenta de esto mientras me lavaba los dientes hace un segundo. A veces deseo que Python tuviera firmas de tipo, ya que esto hubiera sido obvio si se declarase reverse() para devolver una cadena. Gracias. –

+0

Por lo general, obtengo esos momentos ah ah en la ducha a la mañana siguiente. Puede encontrar que pdb (o ipdb) ayuda en los casos en los que desea firmas de tipo. Intenta lanzar 'import pdb; pdb.set_trace() 'en su código en algún momento. http://docs.python.org/library/pdb.html – istruble

4

Las cadenas de consulta deben estar correctamente escapadas y no solo concatenados.

La construcción de una URL con cadena de consulta mediante la concatenación de cadenas es tan mala idea como la construcción de consultas SQL mediante la concatenación de cadenas. Es complicado, poco elegante y especialmente peligroso con una entrada proporcionada por el usuario (que no es de confianza). Desafortunadamente, Django no ofrece una posibilidad sencilla de pasar parámetros de consulta a la función reverse.

estándar de Python urllib sin embargo proporciona la funcionalidad de consulta serie de codificación deseada.

En mi application He creado una función de ayuda de esta manera:

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

Entonces me llaman en la vista de la siguiente manera:

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 

Tenga en cuenta la correcta codificación de caracteres especiales como espacio y signo de exclamación!

+0

No hay necesidad de tomarse la molestia de url codificando los parámetros de cadena de consulta usted mismo. HTTPResponseRedirect lo hará por usted. –

+2

@Declan Shanaghy HTTPResponseRedirect no ofrece ninguna funcionalidad de ensamblaje de cadena de consulta (documentación de django: "El constructor toma un único argumento, la ruta a la que redirigir"), por lo que debe hacerlo usted mismo. Pero no con una simple concatenación de cadenas como lo sugiere istruble: esto no funcionará para valores que contengan caracteres especiales o espacios en blanco. – geekQ

17

Puede utilizar un objeto Django QueryDict:

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() 

Y, por supuesto, se podría escribir un método de conveniencia para ello similar a la respuesta anterior.

3

No debe generar la cadena url mismo. Dadas tus urls.py puede utilizar revertir este modo:

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",)) 

Si utiliza named url patterns, que son ideales para desconectar sus funciones de vista de los identificadores de URL:

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

Uso revertir este modo:

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

Hay _no_way_ que hay alguna distinción entre comillas simples y comillas dobles allí. –

+0

Todo menos mi experiencia ese día del 27 de marzo me dan ganas de editar mi respuesta según su comentario. ¿Alguien más puede confirmarlo? – dbro

+0

Es posible que en una instancia haya olvidado la "r" (o "r" :)) al comienzo de la cadena. No en estos ejemplos, pero en otros donde está usando cosas como \ d, la falta de 'r' hará que python interprete el \ d (y otros) como caracteres especiales, en lugar de dejarlos para que el motor de RE encuentre . Esa es la mejor conjetura que podría surgir. Si realmente puede encontrar la declaración que no funcionó, antes de corregirla, podemos analizarla. –

Cuestiones relacionadas