Django return redirect () z parametrami


83

W mojej funkcji widoku chcę wywołać inny widok i przekazać do niego dane:

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

, gdzie backend jest obiektem registration.backends, a form.cleaned_data jest dyktatem danych formularza (ale oba muszą być wysłane jako * args lub ** kwargs, aby zapobiec zgłaszaniu Don't mix *args and **kwargs in call to reverse()!błędów). Z tego, co znalazłem w dokumentach:

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

Wygląda na to, że muszę podać argument „nazwa-widoku”, ale czy jest to tylko nazwa funkcji widoku, czy nazwa adresu URL? Chciałbym więc zrobić to podobnie do sposobu, w jaki jest to robione w rejestracji django, 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, czy mogę teraz bezpośrednio wywołać moją funkcję widoku, czy też muszę podać jej adres URL? A co ważniejsze, jak powinno wyglądać moje wywołanie funkcji (i adres URL w razie potrzeby)? Zarówno zaplecze, jak i clean_data są przekazywane przez ten widok do późniejszego użycia. Próbowałem tego, ale jest to niewłaściwe:

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

Tak dobrze jak 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):

Odpowiedzi:


66

Po pierwsze, Twoja definicja adresu URL w ogóle nie akceptuje żadnych parametrów. Jeśli chcesz, aby parametry były przekazywane z adresu URL do widoku, musisz zdefiniować je w urlconf.

Po drugie, nie jest wcale jasne, czego oczekujesz od słownika clean_data. Nie zapominaj, że nie możesz przekierować do POST - jest to ograniczenie HTTP, a nie Django - więc twoje clean_data musi albo być parametrem adresu URL (okropne), albo, nieco lepiej, serią parametrów GET - więc adres URL miałby postać:

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

i tak dalej. W tym przypadku field1, field2 i field3 nie są uwzględniane w definicji URLconf - są dostępne w widoku przez request.GET.

Więc twój urlconf wyglądałby tak:

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

a widok wyglądałby tak:

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

a odwrotnie (po zaimportowaniu urllib):

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

Edytowano po komentarzu

Cały sens używania przekierowania i odwrócenia, tak jak to robiłeś, 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 kodu, po prostu zrób to bezpośrednio - nie musisz w ogóle używać odwrotności.

To powiedziawszy, jeśli wszystko, co chcesz zrobić, to zapisać dane, po prostu umieść je w sesji:

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

a jeśli nie będę operował na clean_data w tym widoku, ale przekażę to do późniejszego wykorzystania? Mam wiele pól w
— dyktandzie Cleaning_data,

Nie rozumiem tego komentarza. Proszę wyjaśnić bardziej szczegółowo, aktualizując swoje pytanie, jeśli to konieczne.
— Daniel Roseman,

ten drugi widok zapisze te przesłane dane tylko do dalszego wykorzystania. Ale czy na pewno muszę podać adres URL? Z dokumentów wygląda na to, że bezpośrednio wywołuję widok. Miałem też nadzieję, że wyślę słownik z zapleczem i danymi w redirect () (tak jak to się dzieje w django-register), a następnie w adresie URL (jak ten dict w funkcji rejestru), ale z tego, co widzę, jest to niemożliwe?
— muntu

tak tak tak to jest to !! Zmarnowałem na to tyle czasu zupełnie zapominając o sesjach: / cholera, dzięki !!
— muntu

1
dobra uwaga na temat po prostu wywoływania funkcji, jeśli nie jest potrzebny adres 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)
    # ...
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.