Reputation: 1251
I have a class based view (RegistrationView
) which I'd like to pass a parameter value to upon redirect, as per the following.
# views.py
def hook(request):
return HttpResponseRedirect(reverse('registration_register',
kwargs={'initial': {'email': '[email protected]'}}))
Where my accompanying URL pattern for this is defined as:
# urls.py
urlpatterns = [
url(r'^account/register/$',
RegistrationView.as_view(form_class=RegistrationForm),
name='registration_register'),
]
And initial is a valid parameter value in RegistrationView
.
However, when I run this, I hit the following error, as I have not defined the argument in my urls (and I don't want to have to define the parameter in the url path if possible).
Reverse for 'registration_register' with arguments '()' and keyword arguments '{'initial': {'email': '[email protected]'}}' not found. 1 pattern(s) tried: ['account/register/$']
I came across the following query which discusses passing keyword arguments to class based views, however, I have not been able to get it to work with the above code.
Conceptually what I am trying to achieve is the equivalent of the below, except using a HttpRedirect
instead of generating a straight response.
def hook(request):
return RegistrationView.as_view(
form_class=RegistrationForm, initial={'email': '[email protected]'})(request)
Is anyone able to advise how I can redirect to my view with this initial parameter value?
Upvotes: 0
Views: 2582
Reputation: 29977
You are mixing up a few things.
The parameters you pass to reverse
with args
and kwargs
are used to build a URL. For a view to accept these arguments, the corresponding URL pattern has to have a placeholder for it.
Have a look at this example:
# 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/'
If you want to pass any extra information, you can use query paramters, e.g.
/polls/123/?foo=bar
reverse
is only responsible for the path portion of the URL, i.e until the ?
, you have to build the whole this manually.
django.utils.http import urlencode
path = reverse('detail', kwargs={'question_id': 123})
params = urlencode({'foo': 'bar'})
url = "%s?%s" % (path, params)
You can access query parameters in your view with request.GET
, in this example request.GET.get('foo')
.
Now, regarding your class based view. Simply speaking, as_view()
is the wrong place to look to pass arguments that should be different for each request. Under the hood, the expression RegistrationView.as_view(form_class=RegistrationForm)
creates a factory function, which instantiates a new RegistrationView instance for every request. as_view()
"stores" its arguments and passes them to RegistrationView.__init__()
.
TL;DR:
Pass the email as query parameter, like the parameter next
in the login URL.
/account/register/[email protected]
If your RegistrationView
is a standard FormView
, you can overwrite get_initial
to fetch the parameter.
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
Upvotes: 4
Reputation: 599450
Well, as you say, you haven't defined that parameter in your URL, so I don't know what you think the reverse function is going to do with it. Despite what you say about it being a "valid parameter" for RegistrationView, it's clear that that view doesn't expect that parameter either.
If you want to pass this data via reverse
, you need to write a view that does expect parameters, and give it a URL that accepts those parameters.
An alternative might be to pass this data using the session.
Upvotes: 1