【问题标题】:Test if Django ModelForm has instance测试 Django ModelForm 是否有实例
【发布时间】:2012-03-31 00:52:30
【问题描述】:

如果我在编辑表单中,我想显示一条警告消息,如果我在 Django ModelForm 的创建表单中,我想隐藏它。

form.is_bound 告诉我之前是否填充了表单,但是如何测试 ModelForm 是否设置了现有实例?

我尝试了这个hasattr(form.instance, 'pk'),但这样做是否正确?

干杯,

纳蒂姆

【问题讨论】:

    标签: django django-models django-forms


    【解决方案1】:

    尝试检查form.instance.pk 是否为None。

    hasattr(form.instance, 'pk') 将始终返回 True,因为每个模型实例都有一个 pk 字段,即使它尚未保存到数据库中。

    正如@Paullo 在 cmets 中指出的那样,如果您手动定义主键并指定默认值,则这将不起作用,例如default=uuid.uuid4.

    【讨论】:

    • 这看起来通常是正确的,但对于真正的大型应用程序,其中自动增量 ID 不是一个选项但需要 UUID 之类的东西,失败
    • 感谢您的注意,我使用下面的代码解决了这个问题 @property def from_database(self): return not self._state.adding
    【解决方案2】:

    由于存在的实例将作为参数传递给关键字instance 以创建模型表单,因此您可以在自定义初始化程序中观察到这一点。

    class Foo(ModelForm):
        _newly_created: bool
    
        def __init__(self, *args, **kwargs):
            self._newly_created = kwargs.get('instance') is None
            super().__init__(*args, **kwargs)
    

    【讨论】:

      【解决方案3】:

      我遇到了这个问题,但在我的情况下,我使用 UUID 进行 PK。尽管在大多数情况下接受的答案是正确的,但如果您不使用 Django 默认自动增量 PK,则会失败。

      定义模型属性使我能够从模型、视图和模板中访问此值作为模型的属性

      @property
      def from_database(self):
          return not self._state.adding
      

      【讨论】:

        【解决方案4】:

        我发现 self.instance 设置在 super().init 反正

            class BaseModelForm(BaseForm):
            def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
                         initial=None, error_class=ErrorList, label_suffix=None,
                         empty_permitted=False, instance=None, use_required_attribute=None,
                         renderer=None):
        ...
                if instance is None:
                    # if we didn't get an instance, instantiate a new one
                    self.instance = opts.model()
        

        https://github.com/django/django/blob/65e03a424e82e157b4513cdebb500891f5c78363/django/forms/models.py#L300

        所以我们可以在 super().init 调用之前跟踪实例。 所以我的解决方案是覆盖 init 方法并设置自定义字段以跟踪所有后续表单的方法。

            def __init__(self, *args: Any, instance=None, **kwargs: Any) -> None:
            super().__init__(*args, instance=instance, **kwargs)
            self.is_new_instance = not bool(instance)
        

        及用法:

            def _any_form_method(self):
                if self.is_new_instance:
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-01-02
          • 2015-04-24
          • 1970-01-01
          • 2022-12-10
          • 2012-08-31
          • 2013-04-09
          • 1970-01-01
          相关资源
          最近更新 更多