2010-07-09 14 views
54

Nella mia funzione di visualizzazione voglio chiamare un'altra visualizzazione e passare i dati ad esso:Django ritorno redirect() con parametri

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

, dove back-end è di registration.backends oggetto e form.cleaned_data è un dict dei dati del modulo (ma entrambi devono essere inviati come * args o ** kwargs per impedire l'aumento dell'errore Don't mix *args and **kwargs in call to reverse()!). Da quello che ho trovato nella documentazione:

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

Sembra che ho bisogno di fornire 'un po-view-name' argomento, ma è solo il nome della funzione di visualizzazione, oppure il nome dell'URL ? Quindi vorrei renderlo simile al modo in cui è fatto in django-registrazione, in cui:

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 così ora, posso chiamare direttamente la mia funzione di visualizzazione o devo per fornire un URL per esso? E cosa più importante, come dovrebbe essere la mia chiamata funciotn (e un url se necessario)? Sia il backend che clean_data vengono passati attraverso questa vista per un utilizzo successivo. Ho provato questo, ma è improprio:

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

Oltre a questo:

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

ancora NoReverseMatch. Ma nella registrazione di django, ho visto qualcosa del genere:

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

risposta

52

In primo luogo, la definizione dell'URL non accetta alcun parametro. Se vuoi che i parametri vengano passati dall'URL alla vista, devi definirli in urlconf.

In secondo luogo, non è del tutto chiaro cosa si aspetta che accada al dizionario clean_data. Non dimenticare che non puoi reindirizzare a un POST - questa è una limitazione di HTTP, non di Django - quindi il tuo clean_data deve essere un parametro URL (orribile) o, leggermente migliore, una serie di parametri GET - quindi l'URL sarebbe nella forma:

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

e così via. In questo caso, campo1, campo2 e campo3 sono non inclusi nella definizione URLconf - sono disponibili nella vista tramite request.GET.

Così il vostro urlconf sarebbe:

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

e la vista sarà simile:

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

e il contrario sarebbe (dopo l'importazione urllib):

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

Modificato dopo il commento

L'intero punto dell'utilizzo di reindirizzamento e inversione, come è stato fatto, è che si va all'URL - restituisce un codice Http che induce il browser a reindirizzare al nuovo URL e chiamarlo.

Se si desidera semplicemente richiamare la vista dall'interno del proprio codice, è sufficiente farlo direttamente, non è necessario utilizzare il contrario.

Detto questo, se tutto quello che vogliamo fare è archiviare i dati, poi basta metterlo nella sessione:

request.session['temp_data'] = form.cleaned_data 
+0

e se non funzionerò su clean_data in questa vista, ma semplicemente lo passerò per un utilizzo successivo? Ho molti campi nella dicitura clean_data, quindi vorrei evitare di passarli come stringa get :) – muntu

+0

Non capisco questo commento. Si prega di spiegare in modo più dettagliato, aggiornando la domanda se necessario. –

+0

questa seconda vista memorizzerà solo questi dati inviati per ulteriore utilizzo. Ma sei sicuro di dover fornire l'url per questo? Da documenti sembra che sto chiamando direttamente la vista. Speravo anche solo di inviare un dizionario con backend e dati in redirect() (come è fatto in django-registration) e poi nell'url (come questo dict in funzione register), ma da quello che vedo è impossibile? – muntu

29

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) 
    # ...