在 Django admin 中更改日期字段的默认小部件

Posted

技术标签:

【中文标题】在 Django admin 中更改日期字段的默认小部件【英文标题】:Change the default widget for date fields in Django admin 【发布时间】:2012-01-20 22:15:01 【问题描述】:

如何在 Django ADMIN 中更改 DateField 实例的默认小部件?

我知道如何为 ModelForm - How do you change the default widget for all Django date fields in a ModelForm? 执行此操作 - 通过提供检查字段类型的 formfield_callback 然后提供带有新小部件的表单字段。

但是,我的一些 ModelAdmin 可能已经有一个自定义的 ModelForm,有些还没有。我不想在有日期字段的地方提供/更改 ModelForm(这就是重点)。

不过,可用于子类化的自定义 ModelAdmin 是可以的。无论是否提供了自定义 ModelForm,ModelAdmin 如何更改其表单的日期字段?

也许是一个带有 get_form() 的 ModelAdmin 调用它的 super 然后设置表单的 formfield_callback?似乎有点令人费解,不确定时间,如果有任何 ModelAdmin 需要进一步定制,还需要注意三件事......

P.S.:在 https://***.com/questions/8484811/jquery-datepicker-in-django-admin 被错误地关闭为上述 ModelForm 问题的“完全重复”之后,我问这个问题。我希望现在区别很明显了。

顺便说一句,我个人的动机是 django admin 的默认日期选择器的年份导航。生日真的很糟糕... :-) 是的,有一张三年前的票https://code.djangoproject.com/ticket/9388

【问题讨论】:

【参考方案1】:

我能够在 Django 管理员中自定义默认日期小部件。我遵循了两个教程(来自Simple is Better than Complex 和Django Custom Widget)

    在您的 Django 应用程序中名为 widgets.py 的文件中编写自定义小部件
from django.forms import DateInput


class CustomDatePickerInput(DateInput):
    template_name = "app_name/widgets/custom_datepicker.html"

    class Media:
        css = 
            "all": (
                "https://cdnjs.cloudflare.com/ajax/libs/datepicker/0.6.5/datepicker.min.css",
            )
        
        js = (
            "https://code.jquery.com/jquery-3.4.1.min.js",
            "https://cdnjs.cloudflare.com/ajax/libs/datepicker/0.6.5/datepicker.min.js",
            "https://cdnjs.cloudflare.com/ajax/libs/datepicker/0.6.5/i18n/datepicker.es-ES.min.js",
        )

请注意,您可能需要的 CSS 和 JS 文件应添加到内部 Media 类中,如上面的代码所示。在这种情况下,它正在为自定义 date picker 添加样式。

    为您的小部件定义模板,更多日期选择器选项请参见here,将此文件放入app_name/templates/app_name/widgets/custom_datepicker.html 或确保此模板与您的自定义小部件中template_name 的值匹配:
% load i18n %

% include "django/forms/widgets/input.html" %
% get_current_language as LANGUAGE_CODE %

<script>
  $(function () 
    const DATE_PICKER_OPTIONS = 
      'en-us': 
        format: 'yyyy-mm-dd',
        language: ''
      ,
      'es': 
        format: 'dd/mm/yyyy',
        language: 'es-ES'
      
    ;
    let options = DATE_PICKER_OPTIONS[' LANGUAGE_CODE '];
    $("input[name=' widget.name ']").datepicker(
      format: options.format,
      language: options.language
    );
  );
</script>
    在 Django 管理员中注册模型时,您需要在日期字段中指明要使用的小部件(使用 formfield_overrides
@admin.register(YourModel)
class YourModelAdmin(admin.ModelAdmin):
    formfield_overrides = models.DateField: "widget": CustomDatePickerInput

完成此操作后,您将在 Django 管理中拥有一个用于日期的自定义小部件。请记住,这只是一个指南,您可以通过查看我指出的两个教程来进一步了解。

注意:这个小部件的实现也支持国际化。

【讨论】:

【参考方案2】:

ModelAdmin 只能更改它呈现的表单的小部件,因此很难覆盖传递给它的自定义表单的小部件 - 至少我想不出一个干净的方法来做到这一点。

我可以为您看到一些选项,具体取决于您想要自定义的方式/内容。

    修改为小部件带来魔力的 javascript。如果您的更改可以在那里处理,这似乎很容易。只需提供您自己的js/calendar.jsjs/admin/DateTimeShortcuts.js,就像您覆盖管理员的模板一样。这具有升级友好的额外好处;因为您没有修改 django 代码库;对于使用该小部件的所有表单,更改也将立即生效。

    自定义内置的 django 小部件来做你想做的事。这样做的好处是无需对现有代码进行任何修改即可立即工作,但除非您小心修补源代码,否则升级不友好。来源在django.contrib.admin.widgets

    提供您自己的自定义小部件 - 但是您又回到了遍历代码并用您的自定义实例手动覆盖所有小部件实例的问题。

    使用grappelli 之类的东西并修改模板/js 来做你想做的事。额外的好处是您将免费获得许多其他功能(例如,如果您使用django-admin-tools 插入仪表板,则可以拥有仪表板)。

django 在他们的管理中广泛使用 jquery,并且他们有自己的 jquery 命名空间(django.jQuery);因此,如果您打算做一些自定义小部件,请确保使用正确的命名空间以避免出现奇怪的问题。

【讨论】:

谢谢你。有问题的项目确实在使用 grappelli。鉴于这确实是一个 javascript 问题(“日历不够好”),我会选择 1. 并以这种方式更改日历。 @BurhanKhalid 默认的 javascript 在哪里?

以上是关于在 Django admin 中更改日期字段的默认小部件的主要内容,如果未能解决你的问题,请参考以下文章

Django Admin ForeignKey字段小部件选项和不一致的默认值

在 django admin 中更改字段名称

Django admin 中的默认过滤器

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

更改列表页面上的 django admin 附加字段

Django Admin -> 更改字段顺序,包括内联字段