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

Posted

技术标签:

【中文标题】Django Admin:仅对一个模型字段使用自定义小部件【英文标题】:Django Admin: Using a custom widget for only one model field 【发布时间】:2011-05-09 18:18:54 【问题描述】:

我的模型中有一个DateTimeField 字段。我想在 Django 管理站点中将其显示为复选框小部件。为此,我创建了一个自定义表单小部件。但是,我不知道如何将我的自定义小部件用于这一字段。

Django documentation 解释了如何为特定类型的所有字段使用自定义小部件:

class StopAdmin(admin.ModelAdmin):
    formfield_overrides = 
        models.DateTimeField: 'widget': ApproveStopWidget 
    

但这还不够精细。我只想为 一个 字段更改它。

【问题讨论】:

有一个更清晰的解决方案,使用Meta属性,这里:***.com/a/10293970 【参考方案1】:

为您的 ModelAdmin 创建一个自定义 ModelForm 并将“小部件”添加到其 Meta 类中,如下所示:

class StopAdminForm(forms.ModelForm):
  class Meta:
    model = Stop
    widgets = 
      'approve_ts': ApproveStopWidget(),
    
    fields = '__all__'

class StopAdmin(admin.ModelAdmin):
  form = StopAdminForm

完成!

这方面的文档有点不直观地放在 ModelForm 文档中,在管理文档中没有提及它。见:Creating forms from models

【讨论】:

不幸的是,这似乎只适用于主“编辑”页面,而不是列表显示,而 formfield_overrides 两者都适用。 这值得否决?请花点时间阅读“投票否决”特权说明:***.com/privileges/vote-down。我很肯定我的答案不符合“一个明显不正确且可能危险地不正确的答案”。 意见不一:meta.stackexchange.com/a/112664/146243、meta.stackexchange.com/a/46590/146243、meta.stackexchange.com/a/46596/146243。 从 Django 1.8 开始,您应该将 fields = '__all__' 添加到 Meta。视频***.com/a/28306347/1161025. ... 和approve_ts 是什么意思?然后在下一个答案中重复。 Django 源代码中没有这样的东西,无论是在主题的问题中。【参考方案2】:

在深入研究admin、model field 和form field 代码之后,我相信执行我想要的唯一方法是创建一个自定义模型字段:

models.py

from django.db import models
from widgets import ApproveStopWidget

class ApproveStopModelField(models.DateTimeField):
    pass

class Stop(models.model):
    # Other fields
    approve_ts = ApproveStopModelField('Approve place', null=True, blank=True)

admin.py

from widgets import ApproveStopWidget
from models import ApproveStopModelField

class StopAdmin(admin.ModelAdmin):
    formfield_overrides = 
        ApproveStopModelField: 'widget': ApproveStopWidget 
    

它完成了工作。

暂时,我不会回答这个问题,因为我习惯于忽略显而易见的事情。也许一些 Django smartypants 有更好的解决方案。

【讨论】:

对于那些想知道如何将其与 South 集成的人,此示例所需的行是:from south.modelsinspector import add_introspection_rule add_introspection_rules([], ["^appname\.models\.ApproveStopModelField"])【参考方案3】:

像这样覆盖 formfield_for_dbfield:

class VehicleAdmin(admin.ModelAdmin):
    search_fields = ["name", "colour"]

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'colour':
            kwargs['widget'] = ColourChooserWidget
        return super(VehicleAdmin, self).formfield_for_dbfield(db_field,**kwargs)

(感谢http://www.kryogenix.org/days/2008/03/28/overriding-a-single-field-in-the-django-admin-using-newforms-admin/)

【讨论】:

不错。添加自定义 ModelForm 来更改一个字段的小部件对我来说似乎有点过头了。 刚刚在 Django 1.11.5 中尝试过,效果很好。我的模型有多个 TextField,在 Admin 更改表单中,我需要一些是常规的 【参考方案4】:

Django 的 ModelAdmin.get_changelist_form(self, request, **kwargs) 可以解决 list_editable 的情况

class StopAdminForm(forms.ModelForm):
  class Meta:
    model = Stop
    widgets = 
      'approve_ts': ApproveStopWidget(),
    

class StopAdmin(admin.ModelAdmin):
  form = StopAdminForm

  #just return the ModelForm class StopAdminForm
  def get_changelist_form(self, request, **kwargs):
        return StopAdminForm

参考Django Official documentation on this topic

我希望这会有所帮助

【讨论】:

以上是关于Django Admin:仅对一个模型字段使用自定义小部件的主要内容,如果未能解决你的问题,请参考以下文章

django admin中的ForeignKey字段

在我更改了一些模型字段(Django)之后,尝试访问 django admin 时出现 /admin/myapp/mymodel 的 TypeError

模型字段未在 Django Admin 中显示

模型形式中的 django auto slug,例如 django admin 中的预填充字段

Django 1.11 admin list_filter 在另一个模型中包含字段

Django Admin Cookbook-22如何将一对一关系添加为Admin内联字段