我正在尝试覆盖 django formtools 向导表单小部件,但它只是使用标准小部件
I'm trying to override a django formtools wizard form widget, but it is just using the standard widget
我有以下表格
class ProviderSignUp1(forms.ModelForm):
class Meta:
model = models.Provider
fields = [
'childcare_type_informal',
'childcare_type_accredited',
]
wigdets = {
'childcare_type_informal': PatchRadioSelect(
attrs={
'class':'form-control'
}
),
'childcare_type_accredited': PatchRadioSelect(
attrs={
'class':'form-control'
}
)
}
def clean(self):
cleaned_data = self.cleaned_data
if cleaned_data['childcare_type_informal'] == True and cleaned_data['childcare_type_accredited'] == True:
raise ValidationError("You must select only one type of childcare")
if cleaned_data['childcare_type_informal'] == False and cleaned_data['childcare_type_accredited'] == False:
raise ValidationError("You must select at least one type of childcare")
return super().clean()
小部件定义为
from django.forms.widgets import RadioSelect
class PatchRadioSelect(RadioSelect):
template_name = 'userprofiles/form_widgets/radio.html'
option_template_name = 'userprofiles/form_widgets/radio_option.html'
我的向导是:
PROVIDER_SIGNUP_TEMPLATES = {
'page0': 'userprofiles/provider_signup_wizard/page0.html',
'page1': 'userprofiles/provider_signup_wizard/page1.html',
'page2': 'userprofiles/provider_signup_wizard/page2.html',
'page3': 'userprofiles/provider_signup_wizard/page3.html',
'page4': 'userprofiles/provider_signup_wizard/page4.html',
'page5': 'userprofiles/provider_signup_wizard/page5.html',
'page6': 'userprofiles/provider_signup_wizard/page6.html',
'page7': 'userprofiles/provider_signup_wizard/page7.html',
'page8a': 'userprofiles/provider_signup_wizard/page8.html',
'page8b': 'userprofiles/provider_signup_wizard/page8.html',
'page9': 'userprofiles/provider_signup_wizard/page9.html',
'page10': 'userprofiles/provider_signup_wizard/page10.html',
}
PROVIDER_SIGNUP_FORMS = [
("page0", forms.ProviderSignUp0),
("page1", forms.ProviderSignUp1),
("page2", forms.ProviderSignUp2),
("page3", forms.ProviderSignUp3),
("page4", forms.ProviderSignUp4),
("page5", forms.ProviderSignUp5),
("page6", forms.ProviderSignUp6),
("page7", forms.ProviderSignUp7),
("page8a", forms.ProviderSignUp8a),
("page8b", forms.ProviderSignUp8b),
("page9", forms.ProviderSignUp9),
("page10", forms.ProviderSignUp10),
]
def accredited_only_condition(wizard):
cleaned_data = wizard.get_cleaned_data_for_step('page1') or {}
return cleaned_data.get('childcare_type_accredited', True)
def informal_only_condition(wizard):
cleaned_data = wizard.get_cleaned_data_for_step('page1') or {}
return cleaned_data.get('childcare_type_informal', True)
class ProviderSignUpWizard(SessionWizardView):
form_list = PROVIDER_SIGNUP_FORMS
condition_dict = {
'page2': accredited_only_condition,
'page8a': accredited_only_condition,
'page8b': informal_only_condition,
'page9': informal_only_condition,
}
def get_form_instance(self, step):
if step == 'page4':
return self.instance_dict.get(step, self.request.user)
return self.instance_dict.get(step, self.request.user.provider)
def get_template_names(self):
return [PROVIDER_SIGNUP_TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
provider_instance = models.Provider.objects.get(id=self.request.user.provider.id)
user_instance = models.User.objects.get(id=self.request.user.id)
for form in form_list:
provider_instance = construct_instance(form, provider_instance, form._meta.fields, form._meta.exclude)
user_instance = construct_instance(form, user_instance, form._meta.fields, form._meta.exclude)
provider_instance.save()
user_instance.save()
return redirect(self.request.user.get_provider_profile_url())
def post(self, *args, **kwargs):
form = self.get_form(data=self.request.POST, files=self.request.FILES)
if form.is_valid():
form.save()
if 'services' in form.cleaned_data:
models.Provider.objects.get(id=self.request.user.provider.id).services.set(form.cleaned_data['services'])
if 'features' in form.cleaned_data:
models.Provider.objects.get(id=self.request.user.provider.id).features.set(form.cleaned_data['features'])
if 'informal_phrases' in form.cleaned_data:
models.Provider.objects.get(id=self.request.user.provider.id).informal_phrases.set(form.cleaned_data['informal_phrases'])
return super().post(*args, **kwargs)
我的小部件被忽略,正在使用标准小部件。请注意,我似乎无法更改标准的任何小部件,只能向现有小部件添加属性。我做错了什么?
以防万一其他人遇到同样的问题,我发现如果我在向导的第一个表单中定义 __init__
,我就可以覆盖 __init__
中的小部件以任何形式需要使用它。但是,如果我不在第一种形式中指定 __init__
,它就不起作用。
我认为这更像是一种解决方法而不是解决方案。
我有以下表格
class ProviderSignUp1(forms.ModelForm):
class Meta:
model = models.Provider
fields = [
'childcare_type_informal',
'childcare_type_accredited',
]
wigdets = {
'childcare_type_informal': PatchRadioSelect(
attrs={
'class':'form-control'
}
),
'childcare_type_accredited': PatchRadioSelect(
attrs={
'class':'form-control'
}
)
}
def clean(self):
cleaned_data = self.cleaned_data
if cleaned_data['childcare_type_informal'] == True and cleaned_data['childcare_type_accredited'] == True:
raise ValidationError("You must select only one type of childcare")
if cleaned_data['childcare_type_informal'] == False and cleaned_data['childcare_type_accredited'] == False:
raise ValidationError("You must select at least one type of childcare")
return super().clean()
小部件定义为
from django.forms.widgets import RadioSelect
class PatchRadioSelect(RadioSelect):
template_name = 'userprofiles/form_widgets/radio.html'
option_template_name = 'userprofiles/form_widgets/radio_option.html'
我的向导是:
PROVIDER_SIGNUP_TEMPLATES = {
'page0': 'userprofiles/provider_signup_wizard/page0.html',
'page1': 'userprofiles/provider_signup_wizard/page1.html',
'page2': 'userprofiles/provider_signup_wizard/page2.html',
'page3': 'userprofiles/provider_signup_wizard/page3.html',
'page4': 'userprofiles/provider_signup_wizard/page4.html',
'page5': 'userprofiles/provider_signup_wizard/page5.html',
'page6': 'userprofiles/provider_signup_wizard/page6.html',
'page7': 'userprofiles/provider_signup_wizard/page7.html',
'page8a': 'userprofiles/provider_signup_wizard/page8.html',
'page8b': 'userprofiles/provider_signup_wizard/page8.html',
'page9': 'userprofiles/provider_signup_wizard/page9.html',
'page10': 'userprofiles/provider_signup_wizard/page10.html',
}
PROVIDER_SIGNUP_FORMS = [
("page0", forms.ProviderSignUp0),
("page1", forms.ProviderSignUp1),
("page2", forms.ProviderSignUp2),
("page3", forms.ProviderSignUp3),
("page4", forms.ProviderSignUp4),
("page5", forms.ProviderSignUp5),
("page6", forms.ProviderSignUp6),
("page7", forms.ProviderSignUp7),
("page8a", forms.ProviderSignUp8a),
("page8b", forms.ProviderSignUp8b),
("page9", forms.ProviderSignUp9),
("page10", forms.ProviderSignUp10),
]
def accredited_only_condition(wizard):
cleaned_data = wizard.get_cleaned_data_for_step('page1') or {}
return cleaned_data.get('childcare_type_accredited', True)
def informal_only_condition(wizard):
cleaned_data = wizard.get_cleaned_data_for_step('page1') or {}
return cleaned_data.get('childcare_type_informal', True)
class ProviderSignUpWizard(SessionWizardView):
form_list = PROVIDER_SIGNUP_FORMS
condition_dict = {
'page2': accredited_only_condition,
'page8a': accredited_only_condition,
'page8b': informal_only_condition,
'page9': informal_only_condition,
}
def get_form_instance(self, step):
if step == 'page4':
return self.instance_dict.get(step, self.request.user)
return self.instance_dict.get(step, self.request.user.provider)
def get_template_names(self):
return [PROVIDER_SIGNUP_TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
provider_instance = models.Provider.objects.get(id=self.request.user.provider.id)
user_instance = models.User.objects.get(id=self.request.user.id)
for form in form_list:
provider_instance = construct_instance(form, provider_instance, form._meta.fields, form._meta.exclude)
user_instance = construct_instance(form, user_instance, form._meta.fields, form._meta.exclude)
provider_instance.save()
user_instance.save()
return redirect(self.request.user.get_provider_profile_url())
def post(self, *args, **kwargs):
form = self.get_form(data=self.request.POST, files=self.request.FILES)
if form.is_valid():
form.save()
if 'services' in form.cleaned_data:
models.Provider.objects.get(id=self.request.user.provider.id).services.set(form.cleaned_data['services'])
if 'features' in form.cleaned_data:
models.Provider.objects.get(id=self.request.user.provider.id).features.set(form.cleaned_data['features'])
if 'informal_phrases' in form.cleaned_data:
models.Provider.objects.get(id=self.request.user.provider.id).informal_phrases.set(form.cleaned_data['informal_phrases'])
return super().post(*args, **kwargs)
我的小部件被忽略,正在使用标准小部件。请注意,我似乎无法更改标准的任何小部件,只能向现有小部件添加属性。我做错了什么?
以防万一其他人遇到同样的问题,我发现如果我在向导的第一个表单中定义 __init__
,我就可以覆盖 __init__
中的小部件以任何形式需要使用它。但是,如果我不在第一种形式中指定 __init__
,它就不起作用。
我认为这更像是一种解决方法而不是解决方案。