我在Ubuntu 12.10上使用Django 1.4和Python 2.7。
我有一个表单,我需要动态填充一些下拉菜单(使用jQuery),但需要其中2个是必需的,而第3个是可选的。
我正在使用Tastypie来帮助API获取选项。基本上,第一个下拉列表中包含了学校的行业级代码。选择代码后,将为该代码的所有类别填充类别下拉列表。选择类别后,将为该代码和类别组合的所有子类别填充子类别下拉列表。
我可以要求代码下拉(它没有动态填充)。但是,我很难获得所需的类别下拉菜单。我基本上可以采用2条路线 - 前端验证或后端验证。我正在尝试使用后端验证,以便在需要时轻松创建进一步的验证。
以下是表格:
class SchoolProductForm(forms.ModelForm):
cip_category = forms.ChoiceField(required=True,
choices=(('', '----------'),))
def __init__(self, *args, **kwargs):
super(SchoolProductForm, self).__init__(*args, **kwargs)
self.fields['short_description'].widget = TA_WIDGET
self.fields['salary_info'].widget = TA_WIDGET
self.fields['job_opportunities'].widget = TA_WIDGET
self.fields['related_careers'].widget = TA_WIDGET
self.fields['meta_keywords'].widget = TI_WIDGET
self.fields['meta_description'].widget = TI_WIDGET
self.fields['cip'].queryset = models.CIP.objects.filter(
parent_id__isnull=True)
class Meta:
model = models.SchoolProduct
exclude = ('campus',)
我试图覆盖clean
方法。我试图创建一个特定于字段的clean
方法。似乎都没有用。
以下各种变化:
def clean(self):
super(SchoolProductForm, self).clean()
if cip_category in self._errors:
del self._errors['cip_category']
if self.cleaned_data['cip_category'] == '----------':
self._errors['cip_category'] = 'This field is required.'
return self.cleaned_data
这会导致cip_category
中没有cleaned_data
的错误,这是有道理的,因为它没有验证。
我尝试过特定领域的变化:
def clean_cip_category(self):
data = self.cleaned_data['cip_category']
self.fields['cip_category'].choices = data
return data
但是在页面上出现验证错误,说明我的选择不是可用选项之一。
我尝试创建动态字段类型(多种变体):
class DynamicChoiceField(forms.ChoiceField):
def valid_value(self, value):
return True
class SchoolProductForm(forms.ModelForm):
cip_category = DynamicChoiceField(required=True,
choices=(('', '----------'),))
但它接受----------
作为有效选项(我不想要)并导致错误,因为ORM尝试匹配数据库中的----------
值(它不会找到)。
有什么想法吗?
答案 0 :(得分:1)
我能够在ChoiceField
中稍微改写一下方法来解决这个问题。
我将字段添加到表单中,并使用self.initial
处理预填充:
class SchoolProductForm(forms.ModelForm):
cip_category = common_forms.DynamicChoiceField(
required=True, choices=(('', '----------'),))
def __init__(self, *args, **kwargs):
super(SchoolProductForm, self).__init__(*args, **kwargs)
self.fields['short_description'].widget = TA_WIDGET
self.fields['salary_info'].widget = TA_WIDGET
self.fields['job_opportunities'].widget = TA_WIDGET
self.fields['related_careers'].widget = TA_WIDGET
self.fields['meta_keywords'].widget = TI_WIDGET
self.fields['meta_description'].widget = TI_WIDGET
self.fields['cip'].queryset = models.CIP.objects.filter(
parent_id__isnull=True)
# Get the top parent and pre-populate
if 'cip' in self.initial:
self.initial['cip'] = models.CIP.objects.get(
pk=self.initial['cip']).top_parent()
class Meta:
model = models.SchoolProduct
exclude = ('campus',)
DynamicChoiceField
的位置:
class DynamicChoiceField(forms.ChoiceField):
def valid_value(self, value):
return True
然后,在视图中我添加了form_valid
覆盖中的处理:
def form_valid(self, form):
self.object = form.save(commit=False)
# Handle the CIP code
self.object.cip_id = self.request.POST.get('cip_subcategory')
if self.object.cip_id == '':
self.object.cip_id = self.request.POST.get('cip_category')
self.object.save()