我正在使用
django-formtools的SessionWizardView构建一个双表单向导.我面临的挑战是我需要引用第一个表单中的输入来限制第二个表单上的可用查询集.
为了使它更有趣,我使用crispy表单进行布局,并且查询集需要受到相关项上的方法的限制.
这是我所处的(简化)的要点:
楷模
class Product(models.Model): # pk,name,etc.... catalogitem = ForeignKey("myapp.CatalogItem") colors = ManyToManyField("myapp.Colors") class Colors(models.Model): # pk,etc.... class CatalogItem(models.Model): # Colors are stored within CatalogVariants,which I've left # as a blackBox in this example,since they are retrieved as # a queryset on this model with this method: # pk,etc.... def get_colors(self): # Returns a queryset of color objects.
查看
ProductFormWizard(SessionWizardView): form_list = [ productFormWizard_Step1,productFormWizard_Step2,] def get_context_data(self,**kwargs): # ... pass def get_form_initial(self,step): initial = {} # ... return self.initial_dict.get(step,initial) def process_step(self,form): if self.steps.step1 == 1: pass return self.get_form_step_data(form) def done(self,form_list,**kwargs): return render(self.request,'done.html',{ 'form_data': [form.cleaned_data for form in form_list],})
形式
productFormWizard_Step1(forms.ModelForm): # Defines a form where the user selects a CatalogProduct. model = Product productFormWizard_Step2(forms.ModelForm): """ Defines a form where the user chooses colors based on the CatalogProduct they selected in the prevIoUs step. """ model = Product
根据谷歌的研究和一些SO问题(没有一个是=直接=相关),我假设我需要在colors字段设置.queryset属性,但我不确定在哪里做.两个想法:
>我猜它会以某种方式进入.get_form_initial(),但我对实现这一目标的最佳方法感到茫然.
>或者,相应的代码可能以某种方式进入productFormWizard.get_context_data()方法.
在.get_form_initial()中,我可以这样做:
if step == '1': itemID = self.storage.get_step_data('0').data.get('0-pfProduct',"") if itemID: obj = CatalogItem.objects.get(id=itemID) initial['colors'] = obj.get_get_colors()
但是,这只是选择可用的相关项目……它不限制列表.
附加信息
Python == 3.5.3 Django == 1.10.6 django-crispy-forms == 1.6.1 django-formtools == 2.0
解决方法
解决方案是覆盖View上的.get_form()方法:
def get_form(self,step=None,data=None,files=None): form = super(bzProductFormWizard,self).get_form(step,data,files) if step == '1': past_data = self.get_cleaned_data_for_step('0') product = past_data['product'] form.fields['colors'].queryset = ... #CUSTOM QUERYSET return form