【问题标题】:respond to user actions in a django admin form?在 django 管理表单中响应用户操作?
【发布时间】:2016-04-18 20:55:40
【问题描述】:

我有一个模型,它将不同类型的数据(离散或连续值)存储在一个字段中(类型在另一个字段中)。在该模型的 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

【问题讨论】:

    标签: django django-forms django-admin


    【解决方案1】:

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

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

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

    在我的应用中,这是一个两步过程:

    1. 用户选择类型
    2. 在客户端,该类型字段上的更改处理程序触发调用以获取特定于类型的表单字段。有一个单独的 Django 视图,它用一堆特定于类型的字段和逻辑来实例化一个单独的表单。

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

    【讨论】:

      猜你喜欢
      • 2012-02-17
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 2021-08-03
      • 1970-01-01
      • 2019-09-10
      • 2010-12-10
      • 2022-11-30
      相关资源
      最近更新 更多