在django管理员表单中回复用户操作?

时间:2016-01-13 18:22:28

标签: django django-forms django-admin

我有一个模型,它在一个字段中存储不同类型的数据(离散或连续值)(类型在另一个字段中)。在该模型的ModelForm中,我有一个ChoiceField来选择数据项,还有一个ChoiceField或一个DecimalField来设置项目的值。

当我创建表单时,我根据项目的类型设置值的字段。但是如果我选择不同类型的项目,我想立即更改值字段以匹配。

当表单仍处于活动状态时,即用户正在更改字段值但未单击“提交”按钮时,我无法响应更改。有办法做到这一点吗?最好是在服务器上使用Python,而不是在浏览器端用javascript编写代码。

ChoiceField的选择取自模型,因此无法在任何地方进行硬编码。

以下是一些代码:

class FooProperty (models.Model):
    foo     = models.ForeignKey ('foos.Foo')
    prop    = models.ForeignKey ('foos.FooProperty')
    value   = models.DecimalField (max_digits=15, decimal_places=6) # is an EnumValue id in the case of discrete values.

class FooPropertyForm (forms.ModelForm):
    class Meta:
        model = FooProperty
        fields = ['prop', 'value']

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

        if hasattr (self.instance, 'prop'):
            kind = self.instance.prop.units.kind
            if kind.id != 1:
                values = [(v.id, v.name) for v in EnumValues.objects.filter (kind=kind.id)]
                self.fields ['value'] = forms.ChoiceField (choices=values, required=True)
                self.initial['value'] = int(self.instance.value) # using initial= above doesn't work.
            else:
                # keep the default field.
                pass

1 个答案:

答案 0 :(得分:0)

我有一个类似的多态模型,它根据类型存储不同类型的值(str,int,decimal等)。

你能澄清一下你的问题吗?你说"如果我选择一个不同类型的项目"。您的意思是通过更改浏览器或代码中的表单字段吗?

我假设你的意思是前者。 如果没有来自客户端的某种异步通信,就无法响应Python中的实时表单更改

在我的应用中,它分为两个步骤:

  1. 用户选择类型
  2. 在客户端,该类型字段上的更改处理程序触发调用以获取特定于类型的表单字段。有一个单独的Django视图,它实例化一个单独的表单,其中包含一堆特定于类型的字段和逻辑。
  3. 
    
    var $kind = $('#kind');
    
    $kind.on('change', fetchFormFieldsForKind);
    
    function fetchFormFieldsForKind() {
      var kind = $kind.val();
      $.get(
        "{% url 'form_fields_for_kind' %}?kind=" + $kind.val(),
    
        function (response) {
          newFieldsHtml = response.newFieldsHtml || '';
    
          // Replace all following sibling form fields with the new ones
          // (each field is wrapped by a div with Bootstrap class form-group)
          $kind.closest('.form-group').find('~ .form-group').remove();
          $kind.after(newFieldsHtml);
    
          // or replace the whole form with a rendered ModelForm
        }
      );
    }
    
    
    

    为了完整起见,Django视图看起来像这样:

    def form_fields_for_kind(request, kind):
        """
        Given the string 'kind', return a rendered form that contains 
        any type-specific fields.
        """
        form = YourForm(kind=kind) 
        content = form.as_p()
        return HttpResponse(content, 'text/html')