omit a button from a form (sometimes)
Date: April 19th 2016
Last updated: April 19th 2016
If you use two forms together you inherit all the buttons which have been defined in forms.py. In my example, I was using an update profile form along with django's builtin User form during registration. The problem was that I wanted a button on the update profile page that would allow the user to change their password. It makes no sense to provide access to this button during registration. They don't even have a password yet.
The solution I found easiest was to override the __init__ method using an if statement in the form containing the button.
views.py (using two forms at registration)
This is the part where I use two forms together. I didn't make any changes to this part of the code to omit the button. The thing to note is that SurferForm receives no additional arguments in conjunction with request.POST. This is something I do in a different view (see updateprofile view below).
def register_user(request):
logout(request)
if request.method == 'POST':
user_form = MyRegistrationForm(request.POST)
profile_form = SurferForm(request.POST)
#
if all((user_form.is_valid(), profile_form.is_valid())):
userid = user_form.save()
profile = profile_form.save(commit=False)
profile.user = userid
profile.save()
# authenticate the new user
new_user = authenticate(username=user_form.cleaned_data['username'],
password=user_form.cleaned_data['password1'],)
login(request, new_user)
#return HttpResponseRedirect('/')
#return redirect('/userhome/{}/'.format(new_user.id))
return redirect('/{}/'.format(profile.id))
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
args['profileform'] = SurferForm()
return render(request, 'surferprofile/register.html', args)
forms.py (modification to SurferForm)
Because no additional arguments were sent to SurferForm in the registration view above, register.html would get the default value (None) and omit the button.
class SurferForm(forms.ModelForm):
#<- snipped ->
# I added an argument to the __init__ function
# That is, I added "registration_option=None"
# So when I use the registration form this arg stays as None
def __init__(self, registration_option=None, *args, **kwargs):
super(SurferForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
#<- snipped ->
# Add an if statment to check if the form
# recieved an argument that was anything other than 'None'
# If it did then add the button to the crispy form
if registration_option != None:
self.helper.add_input(Button('changepassword',
"Change password",
css_class='btn-primary',
onclick="javascript:location.href = \
'/changepassword';"))
class Meta:
model = Surfer
fields = [
#<- snipped ->
]
views.py (make sure the appropriate form gets an argument other than None)
@login_required
def updateprofile(request, surfer_id):
surfer = get_object_or_404(Surfer, pk=surfer_id)
# Note the inclusion of 'null'
# 'null' was chosen randomly and does not have specific meaning here
# 'null' gets sent to updateprofile.html within the SurferForm
# which is also an instance of the user requesting the update
form = SurferForm('null', request.POST or None, instance=surfer)
if form.is_valid():
form.save()
return redirect('/{}/'.format(surfer_id))
return render(request, 'surferprofile/updateprofile.html',
{'surfer': surfer, 'form': form})