我在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。
我正在处理Transaction模型的formsets。代替 具有数千个CatalogItems的单选菜单 ForeignKey字段,我想替换三个下拉菜单 group,run和pnumber,唯一标识CatalogItem。 我还想限制后两个下拉菜单的选择 那些可用于当前的运行和pnumbers 选定的产品组(如果是用户,我可以通过AJAX更新它们 更改产品组,但初始页面很重要 如上所述加载而不依赖于AJAX)。
最好的方法是什么?
作为出发点,这是我到目前为止所尝试/考虑的内容:
我的第一种方法是从中排除项目外键字段 表单,通过覆盖add_fields添加替换下拉列表 formset的方法,然后提取数据并填充 在保存模型实例之前手动在模型实例上。它的 简单明了,但它并不是非常可重复使用的 不要认为这是正确的方法。
我的第二种方法是创建一个继承两者的新字段 MultiValueField和ModelChoiceField,以及一个对应的 MultiWidget子类。这似乎是正确的方法。如 Malcolm Tredinnick把它放进去了 a django-users discussion, “一个领域的'智慧'在于Field类。”
我遇到的问题是何时/何地获取选择列表
来自db。我现在的代码在Field __init__
中执行,
但这意味着我必须知道我正在处理哪个ProductGroup
在我甚至可以定义Form类之前,因为我必须实例化
我定义表单时的字段。所以我有一家工厂
从我的观点来看,我在最后一分钟打电话的功能 - 在我知道之后
我有什么CatalogItems以及他们所在的产品组
创建表单/表单集类并实例化它们。它有效,但我
想知道是否有更好的方法。毕竟,这个领域应该是
一旦知道,就能够在以后确定正确的选择
它的当前价值。
另一个问题是我的实现限制了整个formset 与(CatalogItems from)单一的交易 ProductGroup。
我很有趣的第三种可能性就是把它全部放在Widget中 类。一旦我有相关的模型实例,或cid,或 无论给出什么小部件,我都可以获得ProductGroup和 构建下拉列表。这将解决我的问题 第二种方法,但似乎不是正确的方法。
答案 0 :(得分:3)
在formset中设置表单字段选择的一种方法是在表单 init 中覆盖self.fields [' field_name']。的选项,但是因为更多需要动态方法,这是在视图中有效的方法:
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。我认为它是因为formsets和for循环似乎很好地结合在一起:))
答案 1 :(得分:0)
我最后坚持使用第二种方法,但我现在确信这是很长的短路。我不得不在ModelForm和FormField内部挖掘一下,IMO的复杂性超过了最小的好处。
我在关于第一种方法的问题中所写的内容,“这很简单,非常简单”应该是最好的。