【问题标题】:Limiting a Django form's ManyToManyField queryset in a formtools wizard based on selection on previous form根据对先前表单的选择,在表单工具向导中限制 Django 表单的 ManyToManyField 查询集
【发布时间】:2017-08-02 18:29:38
【问题描述】:

我正在使用来自django-formtoolsSessionWizardView 来构建一个包含两种形式的向导。我面临的挑战是我需要引用第一个表单的输入来限制第二个表单上的可用查询集。

为了让它更有趣,我使用清晰的表单进行布局,并且查询集需要通过相关项目上的方法来限制。

这是我所在位置的(非常简化的)要点:

型号

class Product(models.Model):
    # pk, name, etc....
    catalogitem = ForeignKey("myapp.CatalogItem")
    colors = ManyToManyField("myapp.Colors")

class Colors(models.Model):
    # pk, name, 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, name, 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

根据通过 Google 进行的研究和一些 SO 问题(没有一个是 =directly= 相关的),我假设我需要在 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

【问题讨论】:

    标签: forms wizard django-crispy-forms manytomanyfield


    【解决方案1】:

    解决方法是覆盖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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      • 2017-08-06
      • 2011-07-13
      • 2018-11-07
      相关资源
      最近更新 更多