Skip to content

Instantly share code, notes, and snippets.



Last active Jan 19, 2016
What would you like to do?
Breaking Django's form wizard (GenderFormBasic) out across views by manually hacking HiddenInput and RadioSelect
from __future__ import absolute_import
from django import forms
from django.contrib.auth import get_user_model
from django.utils.safestring import mark_safe
from utils.mixins import NoLabelSuffixMixin
from .utils import HiddenInput, RadioSelect
User = get_user_model()
class GenderForm(NoLabelSuffixMixin, forms.ModelForm):
class Meta:
model = User
fields = ('gender',)
widgets = {
'gender': forms.RadioSelect()
class GenderFormBasic(GenderForm):
step = forms.CharField(widget=HiddenInput())
class Meta:
model = User
fields = ('gender',)
widgets = {
'gender': RadioSelect()
from django.forms.widgets import ChoiceFieldRenderer, HiddenInput, RadioChoiceInput, RendererMixin, Select
class HiddenInput(HiddenInput):
A hidden input widget subclass that forces specific id, name, and value
attributes. The widget is used in a form wizard's first form, which can now
be arbitrarily placed in any view and any template.
def build_attrs(self, extra_attrs=None, **kwargs):
attrs = super(HiddenInput, self).build_attrs(extra_attrs, **kwargs)
attrs['id'] = 'id_join_wizard_view-current_step'
attrs['name'] = 'join_wizard_view-current_step'
attrs['value'] = '0'
return attrs
class ChoiceFieldRenderer(ChoiceFieldRenderer):
A ChoiceFieldRenderer subclass that forces a specific name attribute on a
radio button. The attribute mimics the convention of the first form of a
form wizard.
def __init__(self, *args, **kwargs):
super(ChoiceFieldRenderer, self).__init__(*args, **kwargs) = '0-%s' %
class RadioFieldRenderer(ChoiceFieldRenderer):
choice_input_class = RadioChoiceInput
class RadioSelect(RendererMixin, Select):
renderer = RadioFieldRenderer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment