如何修改 Django 中特定类型的所有内置表单字段的默认小部件?

Posted

技术标签:

【中文标题】如何修改 Django 中特定类型的所有内置表单字段的默认小部件?【英文标题】:How do you modify the default widget for all builtin form fields of a certain type in Django? 【发布时间】:2010-10-14 10:50:14 【问题描述】:

这是How do you change the default widget for all Django date fields in a ModelForm?的后续报道。

假设您有大量模型(例如 A-ZZZ)随着您无法控制的其他开发人员的输入而增长,并且您想要更改所有日期字段的输入方式(即通过使用 jQueryUI )。确保使用该新小部件填写所有日期字段的最佳方法是什么?

引用问题的一个建议是:

def make_custom_datefield(f):
   if isinstance(f, models.DateField):
       # return form field with your custom widget here...
   else:
       return f.formfield()

class SomeForm(forms.ModelForm): 
   formfield_callback = make_custom_datefield

   class Meta:
       # normal modelform stuff here...

但是,如果您没有明确的 ModelForm,但 url 模式直接来自模型,是否可以这样做?即你的 url 配置是这样的:

url(r'^A/?$', 'list_detail.object_list', SomeModelA)

其中 SomeModelA 是由 Django 在后台转换为 ModelForm 的模型(不是表单)。

目前在我的系统中,每个模型都没有表格。显式创建表单的唯一要点是添加先前解决方案中建议的 formfield_callback,但这违反了 DRY 原则,并且容易出错且劳动强度大。

我考虑过(如上一个帖子中所建议的那样)创建我自己的具有特殊小部件的字段并使用它而不是内置的。它不是很费力,但可能会出错(不过没有什么是好的 grep 无法修复的)。

感谢您的建议和想法。

【问题讨论】:

【参考方案1】:

听起来您想在整个项目范围内执行此操作(即:您不是在某些情况下尝试执行此操作,而是在所有正在运行的应用程序中尝试执行此操作)。

一种可能性是替换 DateField 类本身的小部件属性。您需要在某个中心位置执行此操作......保证由 django 应用程序的每个运行实例加载的内容。中间件可以帮助解决这个问题。否则,只需将其放入您应用的 __init__ 文件中即可。

您要做的是为 forms.DateField 类本身重新分配小部件属性。创建新的 DateField 时,Django 会检查代码是否在字段属性定义中指定了任何特定的小部件。如果不是,它使用 DateField 的默认值。我假设如果您的场景中的用户确实定义了一个特定的小部件,那么尽管您的全局 API 发生了变化,您仍然希望遵守这一点。

试试这个作为强制默认到其他一些小部件的例子......在这种情况下是一个隐藏输入:

from django import forms
forms.DateField.widget = forms.HiddenInput

class Foo(forms.Form):
    a = forms.DateField()

f = Foo()
print f.fields['a'].widget
# results in <django.forms.widgets.HiddenInput object at 0x16bd910>

【讨论】:

这就是票。谢谢。 太棒了!非常感谢!

以上是关于如何修改 Django 中特定类型的所有内置表单字段的默认小部件?的主要内容,如果未能解决你的问题,请参考以下文章

Django Admin:仅对一个模型字段使用自定义小部件

在 Django 中制作不同的注册表单?

如何检查 django 表单中的字段类型?

在 Django 中自定义管理表单,同时使用自动发现

修改django管理字段以使用特定的queryset和表单小部件

在 django1.3 中使用像 PasswordChangeForm 这样的内置表单和视图