В двух словах легко запомнить PECS
<? extends T>
, если вам нужно извлечь объект типа T
из коллекции. <? super T>
, если вам нужно поместить объекты типа T
в коллекцию. Растущая сложность этого ответа со временем и много требуемых взломов, вероятно, должны предостеречь Вас против выполнения этого вообще. Это полагается на недокументированные внутренние детали реализации администратора, вероятно, повредится снова в будущих версиях Django и не легче реализовать, чем просто нахождение другого календарного виджета JS и использование это.
Однако вот то, что необходимо сделать, если Вы полны решимости сделать эту работу:
Определяют Ваш собственный подкласс ModelForm для Вашей модели (лучше всего для помещения его в forms.py в приложении) и говорят, это для использования AdminDateWidget / AdminTimeWidget / AdminSplitDateTime (замените 'mydate' и т.д. надлежащими именами полей из модели):
from django import forms
from my_app.models import Product
from django.contrib.admin import widgets
class ProductForm(forms.ModelForm):
class Meta:
model = Product
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.fields['mydate'].widget = widgets.AdminDateWidget()
self.fields['mytime'].widget = widgets.AdminTimeWidget()
self.fields['mydatetime'].widget = widgets.AdminSplitDateTime()
Изменение Ваш URLconf для передачи 'form_class': ProductForm вместо 'модели': продукт к универсальному представлению create_object (это будет означать "от my_app.forms, импортирует ProductForm" вместо "из продукта импорта my_app.models", конечно).
В главе Вашего шаблона, включайте {{form.media}} для вывода ссылок на файлы JavaScript.
И hacky часть: администраторские виджеты даты/времени предполагают, что материал i18n JS был загружен, и также требует core.js, но не обеспечивает ни один автоматически. Таким образом в Вашем шаблоне выше {{form.media}} Вам будет нужно:
<script type="text/javascript" src="/my_admin/jsi18n/"></script>
<script type="text/javascript" src="/media/admin/js/core.js"></script>
можно также хотеть использовать следующий администраторский CSS (спасибо Alex для упоминания этого):
<link rel="stylesheet" type="text/css" href="/media/admin/css/forms.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/base.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/global.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/widgets.css"/>
Это подразумевает, что администраторские медиа Django (ADMIN_MEDIA_PREFIX) в/media/admin/-можно изменить это для установки. Идеально Вы использовали бы процессор контекста для передачи, это оценивает шаблону вместо жесткого кодирования его, но это выходит за рамки этого вопроса.
Это также требует, чтобы URL/my_admin/jsi18n/был вручную соединен проводом до представления django.views.i18n.javascript_catalog (или null_javascript_catalog, если Вы не используете I18N). Необходимо сделать это сами вместо того, чтобы пройти приложение администрирования, таким образом, это доступно независимо от того, зарегистрированы ли Вы в администратора (спасибо Jeremy для указания на это). Пример кода для Вашего URLconf:
(r'^my_admin/jsi18n', 'django.views.i18n.javascript_catalog'),
Наконец при использовании Django 1.2 или позже Вам нужен некоторый дополнительный код в Вашем шаблоне, чтобы помочь виджетам найти свои медиа:
{% load adminmedia %} /* At the top of the template. */
/* In the head section of the template. */
<script type="text/javascript">
window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";
</script>
Спасибо lupefiasco для этого дополнения.
Поскольку решением является hackish, я думаю с помощью собственного виджета даты/времени с некоторым JavaScript, более выполнимо.
Да, я закончил тем, что переопределил/admin/jsi18n/url.
Вот то, что я добавил в своем urls.py. Удостоверьтесь, что это выше/admin/url
(r'^admin/jsi18n', i18n_javascript),
И здесь является функцией i18n_javascript, которую я создал.
from django.contrib import admin
def i18n_javascript(request):
return admin.site.i18n_javascript(request)
Дополняя ответ Carl Meyer, я хотел бы прокомментировать, что необходимо поместить тот заголовок в некоторый допустимый блок (в заголовке) в шаблоне.
{% block extra_head %}
<link rel="stylesheet" type="text/css" href="/media/admin/css/forms.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/base.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/global.css"/>
<link rel="stylesheet" type="text/css" href="/media/admin/css/widgets.css"/>
<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/media/admin/js/core.js"></script>
<script type="text/javascript" src="/media/admin/js/admin/RelatedObjectLookups.js"></script>
{{ form.media }}
{% endblock %}
Я часто ссылаюсь на этот пост, и обнаружил, что документация определяет немного менее хакерский способ переопределения виджетов по умолчанию.
( Нет необходимости переопределять метод __init__ ModelForm )
Тем не менее, как упоминает Карл, вам все равно нужно правильно подключить JS и CSS.
forms.py
from django import forms
from my_app.models import Product
from django.contrib.admin import widgets
class ProductForm(forms.ModelForm):
mydate = forms.DateField(widget=widgets.AdminDateWidget)
mytime = forms.TimeField(widget=widgets.AdminTimeWidget)
mydatetime = forms.SplitDateTimeField(widget=widgets.AdminSplitDateTime)
class Meta:
model = Product
Ссылка ] Типы полей , чтобы найти поля формы по умолчанию.
Обновлено решение и обходной путь для SplitDateTime с required = False :
forms.py
from django import forms
class SplitDateTimeJSField(forms.SplitDateTimeField):
def __init__(self, *args, **kwargs):
super(SplitDateTimeJSField, self).__init__(*args, **kwargs)
self.widget.widgets[0].attrs = {'class': 'vDateField'}
self.widget.widgets[1].attrs = {'class': 'vTimeField'}
class AnyFormOrModelForm(forms.Form):
date = forms.DateField(widget=forms.TextInput(attrs={'class':'vDateField'}))
time = forms.TimeField(widget=forms.TextInput(attrs={'class':'vTimeField'}))
timestamp = SplitDateTimeJSField(required=False,)
form.html
<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/admin_media/js/core.js"></script>
<script type="text/javascript" src="/admin_media/js/calendar.js"></script>
<script type="text/javascript" src="/admin_media/js/admin/DateTimeShortcuts.js"></script>
URL. py
(r'^admin/jsi18n/', 'django.views.i18n.javascript_catalog'),
Нижеприведенный вариант также будет работать в крайнем случае, если вышеприведенный не сработал
class PaymentsForm(forms.ModelForm):
class Meta:
model = Payments
def __init__(self, *args, **kwargs):
super(PaymentsForm, self).__init__(*args, **kwargs)
self.fields['date'].widget = SelectDateWidget()
То же самое, что и
class PaymentsForm(forms.ModelForm):
date = forms.DateField(widget=SelectDateWidget())
class Meta:
model = Payments
поместите это в ваш forms.py from django.forms.extras.widgets import SelectDateWidget
Начиная с Django 1.2 RC1, если вы используете трюк с виджетом для выбора даты администратора Django, в ваш шаблон необходимо добавить следующее, иначе вы: Вы увидите URL-адрес значка календаря, на который имеется ссылка через "/ missing-admin-media-prefix /".
{% load adminmedia %} /* At the top of the template. */
/* In the head section of the template. */
<script type="text/javascript">
window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";
</script>