Использование виджетов времени / даты Django в пользовательской форме

Как я могу использовать яркие виджеты даты и времени JavaScript, которые администратор по умолчанию использует с моим пользовательским представлением?

Я просмотрел документацию по формам Django , и он кратко упоминает django.contrib.admin.widgets, но я не знаю, как его использовать?

Вот мой шаблон, который я хочу применить.

<form action="." method="POST"> <table> {% for f in form %} <tr> <td> {{ f.name }}</td> <td>{{ f }}</td> </tr> {% endfor %} </table> <input type="submit" name="submit" value="Add Product"> </form> 

Кроме того, я думаю, что следует отметить, что я на самом деле не написал сам для этой формы, я использую общий вид. Вот запись с url.py:

 (r'^admin/products/add/$', create_object, {'model': Product, 'post_save_redirect': ''}), 

И я уместно новичок во всей работе Django / MVC / MTV, поэтому, пожалуйста, пройдите …

  • Django - невозможно создать миграции для ImageField с динамическим значением upload_to
  • Хранение и удаление тэгов и фильтров Django в моделях Django
  • Как использовать схемы в Django?
  • Почему django использует запятую как десятичный разделитель
  • python - Проблема сохранения символа Unicode для MySQL с Django
  • Django Query с использованием .order_by () и .latest ()
  • Какое ваше любимое решение для управления миграциями баз данных в django?
  • Используются ли атаки CSRF для API?
  • 13 Solutions collect form web for “Использование виджетов времени / даты Django в пользовательской форме”

    Растущая сложность этого ответа с течением времени и требуемые многие хаки, вероятно, должны предостеречь вас от этого. Он полагается на недокументированные внутренние подробности внедрения администратора, скорее всего, снова сломается в будущих версиях Django, и реализовать его проще, чем просто найти другой виджет календаря JS и использовать его.

    Тем не менее, вот что вам нужно сделать, если вы решите сделать эту работу:

    1. Определите свой собственный подкласс ModelForm для своей модели (лучше всего поместить его в form.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() 
    2. Измените свой URLconf, чтобы передать «form_class»: ProductForm вместо «model»: продукт для общего представления create_object (это, конечно, означает «из my_app.forms import ProductForm» вместо «из my_app.models import Product»).

    3. В начало вашего шаблона включите {{form.media}}, чтобы вывести ссылки на файлы Javascript.

    4. И хакерская часть: виджеты даты / времени администратора предполагают, что материал 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). Вы должны сделать это самостоятельно, вместо того, чтобы проходить через приложение администратора, чтобы оно было доступно независимо от того, вошли ли вы в админа (спасибо Джереми, указав это). Пример кода для вашего 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 за это дополнение.

    Поскольку решение хакерское, я думаю, что использование вашего собственного виджета даты / времени с некоторым 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) 

    Начиная с 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> 

    Я часто нахожу, что ссылаюсь на этот пост, и обнаружил, что документация определяет немного менее хакерский способ переопределить виджеты по умолчанию.

    ( Нет необходимости переопределять метод __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 

    Типы ссылочных полей, чтобы найти поля формы по умолчанию.

    Мой головной код для версии 1.4 (некоторые новые и некоторые удалены)

     {% block extrahead %} <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/forms.css"/> <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/base.css"/> <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/global.css"/> <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/widgets.css"/> <script type="text/javascript" src="/admin/jsi18n/"></script> <script type="text/javascript" src="{{ STATIC_URL }}admin/js/core.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin/RelatedObjectLookups.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.init.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}admin/js/actions.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}admin/js/calendar.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin/DateTimeShortcuts.js"></script> {% endblock %} 

    Дополняя ответ Карлом Мейером, я хотел бы прокомментировать, что вам нужно поместить этот заголовок в какой-то действительный блок (внутри заголовка) в вашем шаблоне.

     {% 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 %} 

    (Я пытаюсь прокомментировать людей, предлагающих развернуть свой собственный виджет Календаря, но либо я не вижу кнопку комментария, либо у меня недостаточно ответов).

    Что случилось с СУХОЙ ? Я думаю, что было бы лучше повторно использовать виджет администратора, но, возможно, он должен быть отделен от администратора и проще в использовании. Спасибо за эту информацию в любом случае.

    Мне наконец-то удалось заставить этот виджет работать на dev-сервере, только чтобы он разрывался на развертывание. Я, наконец, решил, что это не стоит делать shoehorning на мой сайт, и написал мой собственный виджет. Это не так гибко, но, вероятно, это будет хорошо работать для многих: http://www.copiesofcopies.org/webl/?p=81

    Нижеследующее также будет работать в крайнем случае, если вышеуказанное не выполнено

     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 

    поместите это в свои формы.py from django.forms.extras.widgets import SelectDateWidget

    Как просто назначить класс вашему виджету, а затем привязать этот класс к датпикеру JQuery?

    Django forms.py:

     class MyForm(forms.ModelForm): class Meta: model = MyModel def __init__(self, *args, **kwargs): super(MyForm, self).__init__(*args, **kwargs) self.fields['my_date_field'].widget.attrs['class'] = 'datepicker' 

    И некоторые JavaScript для шаблона:

      $(".datepicker").datepicker(); 

    Обновленное решение и обходной путь для SplitDateTime с обязательным = 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> 

    urls.py

     (r'^admin/jsi18n/', 'django.views.i18n.javascript_catalog'), 

    В Django 10. myproject / urls.py: в начале URL-адресов

      from django.views.i18n import JavaScriptCatalog urlpatterns = [ url(r'^jsi18n/$', JavaScriptCatalog.as_view(), name='javascript-catalog'), . . .] 

    В моем template.html:

     {% load staticfiles %} <script src="{% static "js/jquery-2.2.3.min.js" %}"></script> <script src="{% static "js/bootstrap.min.js" %}"></script> {# Loading internazionalization for js #} {% load i18n admin_modify %} <script type="text/javascript" src="{% url 'javascript-catalog' %}"></script> <script type="text/javascript" src="{% static "/admin/js/jquery.init.js" %}"></script> <link rel="stylesheet" type="text/css" href="{% static "/admin/css/base.css" %}"> <link rel="stylesheet" type="text/css" href="{% static "/admin/css/forms.css" %}"> <link rel="stylesheet" type="text/css" href="{% static "/admin/css/login.css" %}"> <link rel="stylesheet" type="text/css" href="{% static "/admin/css/widgets.css" %}"> <script type="text/javascript" src="{% static "/admin/js/core.js" %}"></script> <script type="text/javascript" src="{% static "/admin/js/SelectFilter2.js" %}"></script> <script type="text/javascript" src="{% static "/admin/js/admin/RelatedObjectLookups.js" %}"></script> <script type="text/javascript" src="{% static "/admin/js/actions.js" %}"></script> <script type="text/javascript" src="{% static "/admin/js/calendar.js" %}"></script> <script type="text/javascript" src="{% static "/admin/js/admin/DateTimeShortcuts.js" %}"></script> 
    Python - лучший язык программирования в мире.