从重定向将参数传递给基于 class 的视图

Passing a parameter to a class based view from a redirect

我有一个基于 class 的视图 (RegistrationView),我想在重定向时将参数值传递给它,如下所示。

# views.py
def hook(request):
    return HttpResponseRedirect(reverse('registration_register',
                                    kwargs={'initial': {'email': 'user@example.com'}}))

我随附的 URL 模式定义为:

# urls.py
urlpatterns = [
    url(r'^account/register/$',
        RegistrationView.as_view(form_class=RegistrationForm), 
        name='registration_register'),
]

initialRegistrationView中有效的参数值。

但是,当我 运行 这样做时,我遇到了以下错误,因为我没有在我的 url 中定义参数(而且我不想定义参数如果可能,在 url 路径中)。

Reverse for 'registration_register' with arguments '()' and keyword arguments '{'initial': {'email': 'user@example.com'}}' not found. 1 pattern(s) tried: ['account/register/$']

我遇到了以下 query,它讨论了将关键字参数传递给基于 class 的视图,但是,我无法让它与上面的代码一起工作。

从概念上讲,我想要实现的是下面的等效项,除了使用 HttpRedirect 而不是生成直接响应。

def hook(request):
    return RegistrationView.as_view(
         form_class=RegistrationForm, initial={'email': 'user@example.com'})(request)

有谁能告诉我如何使用这个初始参数值重定向到我的视图吗?

好吧,正如您所说,您尚未在 URL 中定义该参数,所以我不知道您认为反向函数将如何处理它。尽管您说它是 RegistrationView 的 "valid parameter",但很明显该视图也不期望该参数。

如果您想通过 reverse 传递此数据,您需要编写一个需要参数的视图,并为其提供一个接受这些参数的 URL。

另一种方法可能是使用会话传递此数据。

你混淆了一些东西。

您通过 argskwargs 传递给 reverse 的参数用于构建 URL。对于接受这些参数的视图,相应的 URL 模式必须有一个占位符。

看看这个例子:

# urls.py
...
url(r'^/polls/(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
...

# views.py
def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

>>> reverse('detail', kwargs={'question_id': 123})
'/polls/123/'

如果你想传递任何额外的信息,你可以使用查询参数,例如

/polls/123/?foo=bar

reverse 只负责 URL 的路径部分,即直到 ?,你必须手动构建整个。

django.utils.http import urlencode
path = reverse('detail', kwargs={'question_id': 123})
params = urlencode({'foo': 'bar'})
url = "%s?%s" % (path, params)

您可以使用 request.GET 在您的视图中访问查询参数,在此示例中 request.GET.get('foo')

现在,关于您基于 class 的观点。简而言之,as_view() 是错误的地方来传递每个请求应该不同的参数。在幕后,表达式 RegistrationView.as_view(form_class=RegistrationForm) 创建了一个工厂函数,它为每个请求实例化一个新的 RegistrationView 实例。 as_view() "stores" 它的参数并将它们传递给 RegistrationView.__init__().

TL;DR:

将电子邮件作为查询参数传递,例如登录 URL 中的参数 next

/account/register/?email=user@example.com

如果您的 RegistrationView 是标准 FormView,您可以覆盖 get_initial 以获取参数。

def get_initial(self):
    initial = super(RegistrationView, self).get_initial()
    email = self.request.GET.get('email')
    if email is not None:
        initial['email'] = email
    return initial