2010-07-09 7 views
54

w mojej funkcji widoku chcę zadzwonić inny widok i przekazać dane do niego:Django przekierowanie return() z parametrami

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

, gdzie backend jest registration.backends sprzeciw i form.cleaned_data jest DICT danych formularza (ale oba muszą być wysłane jako * args lub ** kwargs, aby zapobiec podniesieniu błędu Don't mix *args and **kwargs in call to reverse()!). Z tego co znalazłem w docs:

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

Wygląda na to, że trzeba zapewnić „jakiś-View-name” argumentów, ale jest to tylko nazwa funkcji widoku lub nazwa url ? Więc chciałbym, aby w podobny sposób jak to się robi w django rejestracji, gdzie:

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, więc teraz mogę zadzwonić bezpośrednio moją funkcję widoku czy muszę podać adres URL do niego? I co ważniejsze, jak powinien wyglądać mój funciotn (i URL w razie potrzeby)? Zarówno backend, jak i cleaned_data są właśnie przekazywane przez ten widok do późniejszego użycia. Próbowałem to, ale to jest niewłaściwe:

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

Jak również to:

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

nadal NoReverseMatch. Ale w rejestracji django widziałem coś takiego:

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

Odpowiedz

52

Po pierwsze, twoja definicja adresu URL nie akceptuje żadnych parametrów. Jeśli chcesz przekazać parametry z adresu URL do widoku, musisz zdefiniować je w urlconf.

Po drugie, nie jest jasne, co się stanie ze słownikiem cleaned_data. Nie zapominaj, że nie możesz przekierować do POST - jest to ograniczenie HTTP, a nie Django - więc twoje cleaned_data musi być parametrem URL (fatalnie) lub, nieco lepiej, serią parametrów GET - więc URL będzie mieć postać:

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

i tak dalej. W tym przypadku pola1, pole2 i pole3 są , a nie zawarte w definicji URLconf - są dostępne w widoku za pośrednictwem request.GET.

Więc URLconf byłoby:

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

i widok będzie wyglądać następująco:

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

i odwrotna byłaby (po imporcie urllib):

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

Edytowane po komentarzu

Cały proces używania przekierowania i odwrotnego działania, tak jak to robisz, polega na tym, że przechodzisz do adresu URL - zwraca kod Http, który powoduje, że przeglądarka przekierowuje do nowego adresu URL i wywołuje to.

Jeśli chcesz po prostu wywołać widok z poziomu kodu, po prostu zrób to bezpośrednio - nie musisz w ogóle korzystać z odwrotnego kodu.

Powiedział, że jeśli wszystko, co chcesz zrobić, to zapisać dane, a następnie wystarczy umieścić go w sesji:

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

i jeśli nie będę działać na clean_data w tym widoku, ale po prostu przekazać go do późniejszego wykorzystania? Mam wiele pól w dykcie cleaned_data, więc chciałbym uniknąć podania ich jako ciągu get :) – muntu

+0

Nie rozumiem tego komentarza. Wyjaśnij bardziej szczegółowo, jeśli to konieczne, zaktualizuj swoje pytanie. –

+0

ten drugi widok będzie przechowywać tylko te wysłane dane do dalszego wykorzystania. Ale czy na pewno muszę podać adres URL? Z dokumentów wygląda to tak, jakbym po prostu wywoływał widok bezpośrednio. Miałem także nadzieję, że po prostu wyślę słownik z backendem i danymi w przekierowaniu() (tak jak dzieje się to w rejestracji Django), a następnie w adresie URL (jak ten dyktuj w funkcji rejestru), ale z tego, co widzę, jest niemożliwe? – 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) 
    # ...