Django return redirect () con parámetros

82

En mi función de vista, quiero llamar a otra vista y pasarle datos:

return redirect('some-view-name', backend, form.cleaned_data)

, donde backend es del objeto registration.backends, y form.cleaned_data es un dictado de datos de formulario (pero ambos deben enviarse como * args o ** kwargs para evitar generar Don't mix *args and **kwargs in call to reverse()!errores). De lo que encontré en los documentos:

def my_view(request):
    ...
    return redirect('some-view-name', foo='bar')

Parece que necesito proporcionar el argumento 'some-view-name', pero ¿es solo el nombre de la función de vista o el nombre de la URL? Así que me gustaría hacerlo similar a la forma en que se hace en django-registration, donde:

to, args, kwargs = backend.post_registration_redirect(request, new_user)
return redirect(to, *args, **kwargs)

def post_registration_redirect(self, request, user):
    return ('registration_complete', (), {})

Ok, ahora, ¿puedo llamar directamente a mi función de vista o necesito proporcionar una URL para ello? ¿Y qué es más importante, cómo debería verse mi llamada de función (y una URL si es necesario)? Tanto el backend como los clean_data se pasan a través de esta vista para un uso posterior. He intentado esto, pero es incorrecto:

url(r'^link/$', some-view-name)   
def some-view-name(request, *args):

Tan bien como esto :

return redirect('some_url', backend=backend, dataform.cleaned_data) 
url(r'^link/$', some-view-name)    
def some-view-name(request, backend, data):

todavía NoReverseMatch. Pero en el registro de django, he visto algo como esto:

url(r'^register/$',register,{'backend': 'registration.backends.default.DefaultBackend'}, name='registration_register'),

def register(request, backend, success_url=None, form_class=None,
             disallowed_url='registration_disallowed',
             template_name='user/login_logout_register/registration_form.html',
             extra_context=None):
muntu
fuente

Respuestas:

66

En primer lugar, su definición de URL no acepta ningún parámetro. Si desea que los parámetros se pasen de la URL a la vista, debe definirlos en la urlconf.

En segundo lugar, no está del todo claro lo que espera que suceda con el diccionario clean_data. No olvide que no puede redirigir a un POST; esta es una limitación de HTTP, no de Django, por lo que su clean_data debe ser un parámetro de URL (horrible) o, un poco mejor, una serie de parámetros GET, por lo que la URL estaría en la forma:

/link/mybackend/?field1=value1&field2=value2&field3=value3

y así. En este caso, field1, field2 y field3 no se incluyen en la definición de URLconf; están disponibles en la vista a través de request.GET.

Entonces su urlconf sería:

url(r'^link/(?P<backend>\w+?)/$', my_function)

y la vista se vería así:

def my_function(request, backend):
   data = request.GET

y lo contrario sería (después de importar urllib):

return "%s?%s" % (redirect('my_function', args=(backend,)),
                  urllib.urlencode(form.cleaned_data))

Editado después del comentario

El objetivo de usar redireccionar y revertir, como lo ha estado haciendo, es que va a la URL: devuelve un código Http que hace que el navegador redirija a la nueva URL y la llame.

Si simplemente desea llamar a la vista desde su código, hágalo directamente, no es necesario usar reverse en absoluto.

Dicho esto, si todo lo que quiere hacer es almacenar los datos, simplemente colóquelos en la sesión:

request.session['temp_data'] = form.cleaned_data
Daniel Roseman
fuente
y si no voy a operar en clean_data en esta vista, pero simplemente lo paso para su uso posterior? Tengo muchos campos en el dictado clean_data, así que me gustaría evitar pasarlos como una cadena de obtención :)
muntu
No entiendo este comentario. Explique con más detalle, actualizando su pregunta si es necesario.
Daniel Roseman
esta segunda vista solo almacenará estos datos enviados para su uso posterior. Pero, ¿estás seguro de que necesito proporcionar una URL? Desde los documentos, parece que solo estoy llamando a la vista directamente. También esperaba enviar un diccionario con backend y datos en redirect () (como se hace en django-registration) y luego en la url (como este dict en la función de registro), pero por lo que veo, ¿es imposible?
muntu
si si si eso es !! He perdido tanto tiempo olvidándome por completo de las sesiones: ¡¡Maldita sea, gracias !!
muntu
1
un buen punto sobre simplemente llamar a la función si no se necesita la URL.
maxbellec
60

urls.py:

#...    
url(r'element/update/(?P<pk>\d+)/$', 'element.views.element_update', name='element_update'),

views.py:

from django.shortcuts import redirect
from .models import Element


def element_info(request):
    # ...
    element = Element.object.get(pk=1)
    return redirect('element_update', pk=element.id)

def element_update(request, pk)
    # ...
sergi0
fuente