Is it possible to switch between forms in a view, based on a field value?
I have this view like this:
class telephone_view(UpdateView):
template_name = 'account/telephone.html'
form_class = TelephoneForm
success_url = '/accounts/telephone/'
def get_object(self, queryset=None):
return Profile.get_or_create_for_user(self.request.user)
def form_valid(self, form):
messages.success(self.request, _('Your telephone setting was updated'))
return super(telephone_view, self).form_valid(form)
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(telephone_view, self).dispatch(*args, **kwargs)
I would like to use a different form_class
according to the value of a field not used on the form, essentially because I want different form fields to be available, so, something like:
if self.request.user.profile.status == 'managed':
form_class = TelephoneFormExtended
else:
form_class = TelephoneFormLight
Although I can get the if
to evaluate correctly within the defined functions in the view class telephone_view
after a number of failed attempts I cannot work out how to change the form that is produced.
Am I barking up the wrong tree, is there some other technique to achieve this?
Thanks
Ok, I think I found the answer! I went over my research again, and did some more searching, and I found: https://ccbv.co.uk/ (thanks to https://simpleisbetterthancomplex.com/series/2017/10/09/a-complete-beginners-guide-to-django-part-6.html).
Then I discovered that there’s a function in UpdateView
get_form_class
. So I updated my telephone_view
class:
# views.py
class telephone_view(UpdateView):
template_name = 'account/telephone.html'
#no need to define "form_class" here
#form_class = TelephoneForm
success_url = '/accounts/telephone/'
def get_form_class(self):
if self.request.user.profile.status == 'managed':
messages.success(self.request, _('you got the managed form'))
return TelephoneFormExtended
else:
messages.success(self.request, _('you got the other form'))
return TelephoneFormLight
def get_object(self, queryset=None):
return Profile.get_or_create_for_user(self.request.user)
def form_valid(self, form):
messages.success(self.request, _('Your telephone setting was updated'))
return super(telephone_view, self).form_valid(form)
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(telephone_view, self).dispatch(*args, **kwargs)
Which all magickly works as I expected. All seems too simple, am I missing something!?
Nope, you’re not missing anything. That’s the beauty of building on CBVs, so much of the boilerplate code is already taken care of and there’s usually a hook for anything you may need to do that’s not by default.
1 Like