Skip to content

Instantly share code, notes, and snippets.

@richardcornish

richardcornish/forms.py

Last active Jan 19, 2016
Embed
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)
self.name = '0-%s' % self.name
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