【问题标题】:Assigning initial field values in bound Django admin forms在绑定的 Django 管理表单中分配初始字段值
【发布时间】:2012-01-18 14:31:53
【问题描述】:

我有一个相当简单的 Django 应用程序(Red Hat 上的 v1.3),我使用管理应用程序来创建和修改数据库记录。我的基础模型中的一个字段是日期字段。每次在管理员的新表单或编辑表单中显示相应字段时,我希望该字段的 initial 值为今天的日期(和时间)。如果她愿意,用户可以在之后选择修改它。

我知道我可以在我的模型定义中(即在 models.py 中)设置 default 字段值。首次创建数据库记录时效果很好。但是对于更改表单的后续调用,我分配给默​​认参数 (datetime.datetime.now) 的可调用对象显然不会被调用。

我已经很好地查看并尝试了 stackoverflow 中其他地方描述的所有许多提议的解决方案,但没有成功。其中大部分似乎都围绕着将初始化代码插入ModelForm 子类,例如要么是这样的......

class ConstantDefAdminForm(ModelForm) :
    a_date_field = DateField(initial="datetime.datetime.now")  # or now()
    class Meta :
        model = ConstantDef
        widgets = {
            ...
        }

或者类似的...

class ConstantDefAdminForm(ModelForm) :
    class Meta :
        model = ConstantDef
        widgets = {
            ...
    }
    def __init__(self, ...) :
        # some initialisation of a_date_field
        super(ConstantDefAdminForm, self).__init__(...)

但是这些方法都不起作用。初始字段值始终设置为存储在数据库中的值。我对 Django 文档的阅读是,在表单中施加初始字段值的各种方法仅适用于 unbound 表单,而不适用于 bound 表单。对吧?

但是这种能力(选择性地覆盖当前存储的值)似乎是一个很受欢迎的要求,我相信一定有办法做到这一点。

有没有人成功做到这一点?

提前致谢,

菲尔

【问题讨论】:

    标签: django django-admin


    【解决方案1】:

    这是一种可行的方法。在您的模型管理类中,在绑定表单之前更改 obj.a_date_field 的值。日期字段的“默认”值应该是新值。

    class MyModelAdmin(ModelAdmin):
        ...
        def get_object(self, request, object_id):
            obj = super(MyModelAdmin, self).get_object(request, object_id)
            if obj is not None:
                obj.a_date_field = datetime.now()
            return obj
    

    请注意,get_object 没有记录在案,所以这有点 hacky。

    【讨论】:

    • 酷!这似乎可以解决问题。不确定可能有什么副作用(如果有的话)。但我想我会在适当的时候发现:-) 非常感谢。
    【解决方案2】:

    在 Django 1.4 中,模型声明中的 default=<callable> 效果很好:

    class MyModel(models.Model):
        dt = models.TimeField(null=True, blank=True, default=datetime.datetime.now)
    

    每次添加记录时,字段的默认值都会更新。

    但是使用该字段的default 参数给我带来了DateField 对象的管理日志历史记录的一些问题,这些对象每次都记录为已更改,即使它们没有被修改。所以我采用了基于https://stackoverflow.com/a/11145346/1838607的解决方案:

    import datetime
    
    class MyModelAdminForm(forms.ModelForm):
        class Meta:
            model = MyModel
    
        def __init__(self, *args, **kwargs):
            super(MyModelAdminForm, self).__init__(*args, **kwargs)
    
            self.fields['dt'].initial = datetime.datetime.now
    
    class MyModelAdmin(admin.ModelAdmin):
        form = MyModelAdminForm
        fields = ('dt',)
    

    【讨论】:

      【解决方案3】:

      我也遇到过类似的问题,从here找到解决办法

      我想你会想要做的是:

      class yourAdminModel(admin.ModelAdmin):
      
          fields = ['your_date_field']
      
          def add_view(self, request, form_url="", extra_context=None):
              data = request.GET.copy()
              data['your_date_field'] = datetime.date.today() # or whatever u need
              request.GET = data
              return super(yourAdminModel, self).add_view(request, form_url="", extra_context=extra_context)
      

      【讨论】:

        【解决方案4】:

        应该可以将 auto_now 与您的 DateTime 字段一起使用,according to the docs 将在每次保存表单时自动将值设置为 now()

        【讨论】:

        • 嗨,布兰登。谢谢你的提示。我之前没有发现这些日期字段选项。不幸的是,他们并没有完全做到这一点,因为正如文档所述,当应用 auto_now/auto_now_add 选项中的任何一个时,该字段将呈现为不可编辑。这意味着该字段不会出现在任何管理表单中(尽管这似乎可以通过将字段设置为只读来部分解决 - 并不是说​​这对最终用户非常有用!)。
        【解决方案5】:

        从 Django 1.7 开始,ModelAdmin 中有一个函数 get_changeform_initial_data 用于设置初始表单值:

        def get_changeform_initial_data(self, request):
            return {'dt': datetime.now()}
        

        【讨论】:

        • 这很好,但它只在添加新对象时有效,在更改现有对象时无效。
        猜你喜欢
        • 1970-01-01
        • 2016-08-13
        • 1970-01-01
        • 2013-07-06
        • 1970-01-01
        • 2021-01-22
        • 2015-07-19
        • 1970-01-01
        • 2010-10-23
        相关资源
        最近更新 更多