django 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", который отображается в форме, имеет пустое содержимое. Предположительно, это связано с тем, что нечего связывать набор запросов для ModelChoiceField, который использует ForeignKey Bar для Foo. (Поскольку ничего в "foos" не было сохранено и поэтому не существует в базе данных).

Есть ли другой способ справиться с этим помимо написания настраиваемого поля формы / виджета?

Благодарю.

2 ответа

Решение

Вы можете добавить дополнительное поле к 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

РЕДАКТИРОВАТЬ: на самом деле, теперь, когда я думаю об этом. Те Fooс не будет пкс. Так что нет никакого способа, который когда-либо мог бы работать. Форма должна знать ПК о Foos. Вам действительно нужно сначала сохранить их. Как django узнает, кто из них отправляет обратно форму? Игнорировать ответ ниже.

Я думаю, что вы можете изменить choices переменная на поле. Вам нужно будет это в форме. Так что передайте список Fooс инициалом формы. Что-то вроде этого:

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)

Я знаю, что сделал что-то подобное раньше. Я просто не могу вспомнить точный путь. Что-то вроде этого подхода должно работать, хотя.

Другие вопросы по тегам