【问题标题】:Dynamic model choice field in django formset using multiple select elementsdjango formset中使用多个选择元素的动态模型选择字段
【发布时间】:2011-06-09 19:31:07
【问题描述】:

我在 django-users 列表上发布了这个问题,但那里还没有回复。

我的模型看起来像这样:

class ProductGroup(models.Model):
     name = models.CharField(max_length=10, primary_key=True)
     def __unicode__(self): return self.name

class ProductRun(models.Model):
     date = models.DateField(primary_key=True)
     def __unicode__(self): return self.date.isoformat()

class CatalogItem(models.Model):
     cid     = models.CharField(max_length=25, primary_key=True)
     group   = models.ForeignKey(ProductGroup)
     run     = models.ForeignKey(ProductRun)
     pnumber = models.IntegerField()
     def __unicode__(self): return self.cid
     class Meta:
         unique_together = ('group', 'run', 'pnumber')

class Transaction(models.Model):
     timestamp   = models.DateTimeField()
     user        = models.ForeignKey(User)
     item        = models.ForeignKey(CatalogItem)
     quantity    = models.IntegerField()
     price       = models.FloatField()

假设大约有 10 个 ProductGroups 和 10-20 个相关 ProductRuns 在任何给定时间。每组有 20-200 个不同的 产品编号(pnumber),所以至少有几千个 目录项。

我正在为事务模型开发表单集。代替 具有数千个 CatalogItems 的单选菜单 ForeignKey 字段,我想替换三个下拉菜单,为 group、run 和 pnumber,它们唯一地标识 CatalogItem。 我还想将后两个下拉列表中的选择限制为 那些可用于当前的运行和 pnumber 选定的产品组(如果用户我可以通过 AJAX 更新它们 更改产品组,但重要的是初始页面 在不依赖 AJAX 的情况下按所述加载)。

最好的方法是什么?

作为出发点,这是我迄今为止尝试/考虑过的:

我的第一种方法是从 表单,通过覆盖 add_fields 添加替代下拉列表 方法,然后提取数据并填充 在保存它们之前手动在模型实例上的字段。它是 直截了当而且非常简单,但它不是很可重用,我 不要认为这是正确的做法。

我的第二种方法是创建一个继承两者的新字段 MultiValueField 和 ModelChoiceField,以及对应的 MultiWidget 子类。这似乎是正确的方法。作为 马尔科姆·特雷丁尼克 a django-users discussion, “字段的‘智能’在于 Field 类。”

我遇到的问题是何时/何处获取选择列表 从分贝。我现在拥有的代码在字段的__init__ 中完成, 但这意味着我必须知道我正在处理哪个 ProductGroup 在我什至可以定义 Form 类之前,因为我必须实例化 我定义表单时的字段。所以我有一个工厂 我在最后一刻从我的视野中调用的函数——在我知道之后 我有哪些 CatalogItems 以及它们属于哪个产品组 创建表单/表单集类并实例化它们。它有效,但我 想知道是否有更好的方法。毕竟,该领域应该是 能够在很久以后确定正确的选择,一旦它知道 它的当前值。

另一个问题是我的实现限制了整个表单集 到与(CatalogItems from)单个相关的事务 产品组。

我认为的第三种可能性是将其全部放在小部件中 班级。一旦我有了相关的模型实例,或者 cid,或者 无论给出什么小部件,我都可以获得 ProductGroup 和 构建下拉菜单。这将解决我的问题 第二种方法,但似乎不是正确的方法。

【问题讨论】:

    标签: django forms


    【解决方案1】:

    在表单集中设置表单的字段选择的一种方法是在表单的__init__ 方法中覆盖self.fields['field_name'].choices,但由于需要更动态的方法,以下是在视图中有效的方法:

    from django.forms.models import modelformset_factory
    user_choices = [(1, 'something'), (2, 'something_else')]  # some basic choices
    PurchaserChoiceFormSet = modelformset_factory(PurchaserChoice, form=PurchaserChoiceForm, extra=5, max_num=5)
    my_formset = PurchaserChoiceFormSet(self.request.POST or None, queryset=worksheet_choices)
    
    # and now for the magical for loop
    for choice_form in my_formset:
        choice_form.fields['model'].choices = user_choices
    

    我无法找到答案,但尝试了一下,它在 Django 1.6.5 中有效。我想通了,因为 formset 和 for 循环似乎很好地结合在一起:)

    【讨论】:

      【解决方案2】:

      我最终坚持使用第二种方法,但现在我确信这是非常长的捷径。我不得不在 ModelForm 和 FormField 内部进行一些研究,而 IMO 的复杂性超过了最小的好处。

      我在关于第一种方法的问题中写道,“它很简单,非常简单”,应该是提示。

      【讨论】:

        猜你喜欢
        • 2011-08-25
        • 1970-01-01
        • 2015-10-30
        • 1970-01-01
        • 2017-05-04
        • 2017-07-11
        • 2017-10-04
        • 2017-12-24
        • 2011-02-13
        相关资源
        最近更新 更多