重写DateTimeShortcuts扩展AdminTimeWidget时遇未定义错误求助
问题描述
尝试通过重写DateTimeShortcuts为AdminTimeWidget添加更多时间选项,但控制台抛出以下错误:
Uncaught ReferenceError: DateTimeShortcuts is not definedjQuery.Deferred exception: DateTimeShortcuts is not defined ReferenceError: DateTimeShortcuts is not defined at HTMLDocument
相关实现代码如下:
自定义JS文件
(function($) { $(document).ready(function() { DateTimeShortcuts.clockHours.default_ = [ ['16:30', 16.5], ['17:30', 17.5], ['18:00', 18], ['19:00', 19], ['20:00', 20], ]; DateTimeShortcuts.handleClockQuicklink = function (num, val) { let d; if (val == -1) { d = DateTimeShortcuts.now(); } else { const h = val | 0; const m = (val - h) * 60; d = new Date(1970, 1, 1, h, m, 0, 0); } DateTimeShortcuts.clockInputs[num].value = d.strftime(get_format('TIME_INPUT_FORMATS')[0]); DateTimeShortcuts.clockInputs[num].focus(); DateTimeShortcuts.dismissClock(num); }; }); })(jQuery);
ModelAdmin配置
@admin.register(models.MyModel) class MyAdminModel(): # 其他配置 list_filter = [("created", custom_titled_datetime_range_filter("By created"))] class Media: js = ("admin/js/DateTimeShortcuts.js",)
自定义日期范围过滤器
def custom_titled_datetime_range_filter(title): class CustomDateTimeRangeFilter(DateTimeRangeFilter): def __init__(self, field, request, params, model, model_admin, field_path): super().__init__(field, request, params, model, model_admin, field_path) self.title = title return CustomDateTimeRangeFilter
错误原因及解决方案
1. ModelAdmin未继承基类
你的MyAdminModel没有继承admin.ModelAdmin,导致Media类无法被Django Admin正确识别加载,直接影响JS文件的引入逻辑。
修改ModelAdmin定义:
@admin.register(models.MyModel) class MyAdminModel(admin.ModelAdmin): # 补充继承基类 # 其他配置 list_filter = [("created", custom_titled_datetime_range_filter("By created"))] class Media: # 先加载Django自带的DateTimeShortcuts,再加载自定义JS(替换为你的自定义JS实际路径) js = ( "admin/js/DateTimeShortcuts.js", "admin/js/custom_datetime_shortcuts.js", )
2. JS加载顺序错误
自定义JS依赖DateTimeShortcuts对象,必须确保Django自带的DateTimeShortcuts.js先加载完成,再执行你的自定义代码。如果顺序颠倒,就会出现对象未定义的错误。
注意:不同Django版本的DateTimeShortcuts.js路径有差异:
- Django 2.x及更早:
admin/js/DateTimeShortcuts.js - Django 3.x+:
admin/js/django/DateTimeShortcuts.js
请根据你的Django版本调整路径。
3. 增加加载检查(可选)
如果调整顺序后仍有问题,可以在自定义JS中增加存在性检查,确保DateTimeShortcuts加载完成后再执行修改逻辑:
(function($) { function waitForDateTimeShortcuts() { if (typeof DateTimeShortcuts !== 'undefined') { DateTimeShortcuts.clockHours.default_ = [ ['16:30', 16.5], ['17:30', 17.5], ['18:00', 18], ['19:00', 19], ['20:00', 20], ]; DateTimeShortcuts.handleClockQuicklink = function (num, val) { let d; if (val == -1) { d = DateTimeShortcuts.now(); } else { const h = val | 0; const m = (val - h) * 60; d = new Date(1970, 1, 1, h, m, 0, 0); } DateTimeShortcuts.clockInputs[num].value = d.strftime(get_format('TIME_INPUT_FORMATS')[0]); DateTimeShortcuts.clockInputs[num].focus(); DateTimeShortcuts.dismissClock(num); }; } else { setTimeout(waitForDateTimeShortcuts, 100); } } $(document).ready(function() { waitForDateTimeShortcuts(); }); })(jQuery);
4. 版本兼容替代方案(高版本Django)
部分新版本Django对Admin JS结构做了调整,直接修改DateTimeShortcuts可能失效。此时建议通过自定义AdminTimeWidget实现需求:
from django.contrib.admin.widgets import AdminTimeWidget class CustomAdminTimeWidget(AdminTimeWidget): def get_context(self, name, value, attrs): context = super().get_context(name, value, attrs) # 传递自定义时间选项到模板 context['custom_time_choices'] = [ ('16:30', '16:30'), ('17:30', '17:30'), ('18:00', '18:00'), ('19:00', '19:00'), ('20:00', '20:00'), ] return context # 在ModelAdmin中使用自定义Widget @admin.register(models.MyModel) class MyAdminModel(admin.ModelAdmin): def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'your_time_field': # 替换为你的时间字段名 kwargs['widget'] = CustomAdminTimeWidget return super().formfield_for_dbfield(db_field, **kwargs)
之后复制Django自带的admin/widgets/time.html模板,添加自定义时间选项的渲染逻辑即可。
内容的提问来源于stack exchange,提问作者Saidamir
相关产品推荐
相关产品推荐

