【问题标题】:django modelchoicefield with unsaved models带有未保存模型的 django modelchoicefield
【发布时间】:2014-04-20 14:13:30
【问题描述】:

全部,

我是否有一种直接的方法来显示一个使用模型选择字段的表单来显示尚未保存的模型?

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))

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

除了编写自定义表单域/小部件之外,还有其他方法可以解决这个问题吗?

谢谢。

【问题讨论】:

    标签: python django django-forms modelform


    【解决方案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
    

    【讨论】:

    • 是的,我正在做这样的事情。我在表单的 init fn 中使用 ChoiceField 覆盖表单字段。然后我将一组选择传递给字段的构造函数。在表单的保存方法中,我将在选择字段中保存与所选项目对应的 Foo,然后将 bar.foo 设置为该 ID。
    【解决方案2】:

    编辑:实际上,现在我想起来了。那些Foos 不会有pks。所以没有办法可以工作。表单需要知道Foos 的pk。你真的只需要先保存它们。 django 在回发表单时如何知道哪个是哪个?忽略下面的答案。

    我认为您可以更改字段上的choices 变量。您将需要在表格中填写。所以将Foos 的列表传递给表单的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)
    

    我知道我以前做过类似的事情。我只是不记得确切的方式。不过,这种方法应该可以工作。

    【讨论】:

      猜你喜欢
      • 2015-04-17
      • 1970-01-01
      • 2021-08-17
      • 2010-10-31
      • 2016-07-07
      • 1970-01-01
      • 2020-07-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多