Django: как изменить выбор AdminTimeWidget
на AdminTimeWidget
отображается в admin для DateTimeField
отображает значок часов, и при нажатии у вас есть выбор между: "теперь полночь 6:00 полдень".
Как я могу изменить эти варианты на "16h 17h 18h"?
6 ответов
У Криса есть отличный ответ. В качестве альтернативы вы можете сделать это, используя только javascript. Поместите следующий javascript на страницы, где вы хотите различные параметры времени.
DateTimeShortcuts.overrideTimeOptions = function () {
// Find the first time element
timeElement = django.jQuery("ul.timelist li").eq(0).clone();
originalHref = timeElement.find('a').attr('href');
// remove all existing time elements
django.jQuery("ul.timelist li").remove();
// add new time elements representing those you want
var i=0;
for (i=0;i<=23;i++) {
// use a regular expression to update the link
newHref = originalHref.replace(/Date\([^\)]*\)/g, "Date(1970,1,1," + i + ",0,0,0)");
// update the text for the element
timeElement.find('a').attr('href', newHref).text(i+"h");
// Add the new element into the document
django.jQuery("ul.timelist").append(timeElement.clone());
}
}
addEvent(window, 'load', DateTimeShortcuts.overrideTimeOptions);
подкласс AdminTimeWidget
чтобы включить измененный DateTimeShortcuts.js (доберитесь до этого через секунду), затем подкласс AdminSplitDateTime
чтобы включить ваш подкласс MyAdminTimeWidget
вместо стандартного Django one:
from django.contrib.admin.widgets import AdminTimeWidget
from django.conf import settings
class MyAdminTimeWidget(AdminTimeWidget):
class Media:
js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
settings.MEDIA_URL + "js/admin/DateTimeShortcuts.js")
class MyAdminSplitDateTime(AdminSplitDateTime):
def __init__(self, attrs=None):
widgets = [AdminDateWidget, MyAdminTimeWidget]
forms.MultiWidget.__init__(self, widgets, attrs)
секретный соус в django/contrib/admin/media/js/admin/DateTimeShortcuts.js
. Это создает список, который вы хотите изменить. Скопируйте этот файл и вставьте его в . Соответствующий код нужно изменить на линии 85-88:
quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().strftime('" + time_format + "'));");
quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,0,0,0,0).strftime('" + time_format + "'));");
quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,6,0,0,0).strftime('" + time_format + "'));");
quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,12,0,0,0).strftime('" + time_format + "'));");
просто добавьте / удалите из / измените этот бит JavaScript к содержанию вашего сердца.
наконец, прикрепите новый виджет к любому DateTimeFields вам нравится. Ваш лучший выбор для этого, вероятно, будет formfield_overrides
атрибут on ModelAdmin
:
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.DateTimeField: {'widget': MyAdminSplitDateTime},
}
Я попытался использовать этот метод и обнаружил, что приведенный выше javascript не работает, когда в форме присутствуют несколько datetime.
вот что я сделал.
в моем разделе ModelAdmin я добавил:
class Media:
js = ('js/clock_time_selections.js',)
затем в файле js:
$('document').ready(function () {
DateTimeShortcuts.overrideTimeOptions = function () {
var clockCount = 0;
console.log('ready');
$('ul.timelist').each(function () {
var $this = $(this);
var originalHref = $this.find('a').attr('href');
console.log(originalHref);
$this.find('li').remove();
for (i=8; i <= 20; i++) {
var newLink = '<li><a href="javascript:DateTimeShortcuts.handleClockQuicklink('+ clockCount + ', ' + i
+ ');"> ' + i + ':00h</a></li>';
$this.append(newLink);
}
//console.log($this.html());
clockCount++;
});
};
addEvent(window, 'load', DateTimeShortcuts.overrideTimeOptions);
});
Примечание: я должен был поместить внутри документа.готов, потому что я обнаружил, что не могу контролировать, где скрипт был включен в страницу (кажется, был загружен до файлов JS календаря по умолчанию).
переопределение JS на DateTimeShortcuts.overrideTimeOptions функция работает только с одной формой (ошибка: изменение времени в дочерней модели влияет на родительскую модель, поэтому вы не можете изменить timefield в форме дочерней модели этим виджетом)
Если вы хотите использовать пользовательские параметры с проходной:
на / static / admin/js/admin / DateTimeShortcuts.js заменить:
quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().strftime('" + time_format + "'));");
quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,0,0,0,0).strftime('" + time_format + "'));");
quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,6,0,0,0).strftime('" + time_format + "'));");
quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,12,0,0,0).strftime('" + time_format + "'));");
by:
for(j=6;j<=23;j++){
quickElement("a", quickElement("li", time_list, ""), j+":00", "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1," + j + ",0,0,0).strftime('" + time_format + "'));");
}
Я пошел с гораздо более простым подходом, и это сработало для меня. Я просто добавил варианты в свою модель, используя следующий код:
class Class(Model):
program = ForeignKey('Program')
time_of_the_day = TimeField(choices=(
(datetime.datetime.strptime('7:00 am', "%I:%M %p").time(), '7:00 am'),
(datetime.datetime.strptime('8:00 am', "%I:%M %p").time(), '8:00 am'),
(datetime.datetime.strptime('9:00 am', "%I:%M %p").time(), '9:00 am'),
(datetime.datetime.strptime('6:00 pm', "%I:%M %p").time(), '6:00 pm'),
(datetime.datetime.strptime('7:00 pm', "%I:%M %p").time(), '7:00 pm'),
(datetime.datetime.strptime('8:00 pm', "%I:%M %p").time(), '8:00 pm'),
(datetime.datetime.strptime('9:00 pm', "%I:%M %p").time(), '9:00 pm'),
))
надеюсь, что это помогает
есть лучшее решение. После прочтения DateTimeShortcuts.js можно упростить до:
(function ($) {
$(document).ready(function () {
DateTimeShortcuts.clockHours.default_ = [];
for (let hour = 8; hour <= 20; hour++) {
let verbose_name = new Date(1970, 1, 1, hour, 0, 0).strftime('%H:%M');
DateTimeShortcuts.clockHours.default_.push([verbose_name, hour])
}
});
})(django.jQuery);
затем добавьте этот код в файл javascript в ' static / / time-shortcuts.js ' и добавьте Meta в свою модель администратора:
from django.contrib import admin
from .models import MyModel
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = [
'<myapp>/time-shortcuts.js',
]