具有未保存模型的django modelchoicefield

时间:2014-03-15 04:04:33

标签: python django django-forms modelform

所有

对于我来说,是否有一种直接的方式来显示一个使用modelchoicefield的表单来保存尚未保存的模型?

class Foo(models.Model):
  name = models.CharField(max_length=42)

class Bar(models.Model):
  name = models.CharField(max_length=42)
  foo = models.ForeignKey("Foo",blank=True,null=True)

class BarForm(ModelForm):
  class Meta:
    model = Bar
  pass

def create_new_bar(request):
  foos = [Foo(name='foo1'), Foo(name='foo2'), Foo(name='foo3')]
  bar = Bar(name='bar',foo=foos[0])
  form = BarForm(instance=bar)
  return render_to_response('bar_template.html',{"form" : form},context_instance=RequestContext(request))

但是在表单中呈现的“select”小部件具有空内容。据推测,这是因为没有任何东西可以将查询集绑定到Bar的ForeignKey to Foo使用的ModelChoiceField。 (因为“foos”中没有任何内容已保存,因此数据库中不存在。)

除了编写自定义的formfield / widget之外,还有其他方法可以解决这个问题吗?

感谢。

2 个答案:

答案 0 :(得分:1)

编辑:实际上,现在我想到了。那些Foo不会有pks。所以没有办法可行。表单需要知道Foo的pk。你真的只需要先保存它们。 django如何知道哪一个在回发表格时是哪一个? IGNORE ANWWER BELOW。

我认为您可以更改字段上的choices变量。你需要在表格中。因此,将Foo的列表传递给表单的init。像这样:

class BarForm(ModelForm):
    class Meta:
        model = Bar

    def __init__(self, foo_list, *args, **kwargs):
        super(BarForm, self).__init__(*args, **kwargs)

        self.fields['foo'].choices = foo_list

然后在视图中:

foos = [Foo(name='foo1'), Foo(name='foo2'), Foo(name='foo3')]
bar = Bar(name='bar', foo=foos[0])
form = BarForm(foos, instance=bar)

我知道我以前做过这样的事情。我只是记不起确切的方式。这样的方法应该有用。

答案 1 :(得分:1)

您可以使用预定义的选项向BarForm添加其他字段 - 例如fooempty。如果Foo表为空,将显示该字段。试试这个(未经测试):

class BarForm(ModelForm):
  FOO_CHOICES = (
    (0, 'Choice1'),
    (1, 'Choice2'),
    (2, 'Choice3'),
  )
  fooempty = forms.ChoiceField(required=False, label='lbl', choices=FOO_CHOICES)
  class Meta:
    model = Bar

  def __init__(self, *args, **kwargs):
    super(BarForm, self).__init__(*args, **kwargs)
    if self.fields['foo'].queryset.count(): # Foo empty?
      self.fields['fooempty'].widget = forms.HiddenInput()
    else:
      self.emptyflag
      self.fields['foo'].widget = forms.HiddenInput() 

  def save(self, commit=True):
    bar = super(BarForm, self).save(commit=False)
    if self.emptyflag:
      bar.foo_id = self.cleaned_data['fooempty']
    bar.save()
    return bar