Django возвращает redirect () с параметрами

83

В моей функции просмотра я хочу вызвать другое представление и передать ему данные:

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

, где backend - это объект registration.backends, а form.cleaned_data - это данные формы (но оба должны быть отправлены как * args или ** kwargs, чтобы предотвратить возникновение Don't mix *args and **kwargs in call to reverse()!ошибки). Из того, что я нашел в документации:

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

Похоже, мне нужно указать аргумент some-view-name, но это просто имя функции просмотра или имя URL-адреса? Поэтому я хотел бы сделать его похожим на то, как это делается в django-registration, где:

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', (), {})

Хорошо, теперь могу я вызвать функцию просмотра напрямую или мне нужно указать для нее URL-адрес? И что более важно, как должен выглядеть мой вызов funciotn (и URL-адрес, если необходимо)? И backend, и cleaned_data просто проходят через это представление для последующего использования. Я пробовал это, но это неправильно:

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

Так же как и это :

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

по-прежнему NoReverseMatch. Но в django-registration я видел что-то вроде этого:

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):
мунту
источник

Ответы:

66

Во-первых, ваше определение URL-адреса вообще не принимает никаких параметров. Если вы хотите, чтобы параметры передавались из URL-адреса в представление, вам необходимо определить их в urlconf.

Во-вторых, совсем не ясно, что вы ожидаете от словаря cleaned_data. Не забывайте, что вы не можете перенаправить на POST - это ограничение HTTP, а не Django - поэтому ваши cleaned_data должны быть либо параметром URL (ужасно), либо, что немного лучше, серией параметров GET - так что URL будет в форме:

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

и так далее. В этом случае field1, field2 и field3 не включены в определение URLconf - они доступны в представлении через request.GET.

Итак, ваш urlconf будет таким:

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

и вид будет выглядеть так:

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

и наоборот (после импорта urllib):

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

Отредактировано после комментария

Весь смысл использования перенаправления и реверса, как вы это делали, заключается в том, что вы переходите по URL-адресу - он возвращает Http-код, который заставляет браузер перенаправлять на новый URL-адрес и вызывать его.

Если вы просто хотите вызвать представление из своего кода, просто сделайте это напрямую - нет необходимости использовать реверс.

Тем не менее, если все, что вы хотите сделать, это сохранить данные, просто поместите их в сеанс:

request.session['temp_data'] = form.cleaned_data
Дэниел Розман
источник
и если я не буду работать с cleaned_data в этом представлении, а просто передам его для дальнейшего использования? У меня много полей в dict cleaned_data, поэтому я бы не хотел передавать их как строку для получения :)
muntu
Я не понимаю этого комментария. Пожалуйста, объясните более подробно, при необходимости обновив свой вопрос.
Daniel Roseman
это второе представление будет хранить только эти отправленные данные для дальнейшего использования. Но вы уверены, что мне нужно указать для этого URL? Из документов похоже, что я просто вызываю представление напрямую. Также я надеялся просто отправить словарь с бэкэндом и данными в redirect () (как это делается в django-registration), а затем в URL-адресе (как этот dict в функции регистрации), но из того, что я вижу, это невозможно?
muntu 09
да да да вот оно что !! Я потратил на это столько времени, полностью забыв о сессиях: / блин, спасибо !!
muntu 09
1
Хороший момент в том, чтобы просто вызвать функцию, если 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
источник