Моя библиотека - социальная сеть любителей книг

Интро

В одном проекте, мне понадобился визуальный календарик. Брать “сторонние” разработки не хотелось, т.к. хороший календарик уже есть в админке Django. Осталось только его достать )

Легко?

Достать календарик проще простого:

from django import forms
from django.contrib.admin.widgets import AdminDateWidget

class TestForm(forms.Form):
    datefrom = forms.DateTimeField(label='Дата',  widget=AdminDateWidget)

Выглядит все просто и логично. Но, к сожалению этого не достаточно. Данному виджету трубуются дополнительные JS & CSS файлы.

Вначале я попытался сделать свой виджет унаследовав его от AdminDateWidget и дополнив его Meta-класс необходимыми js & css файлами. Но ничего не получилось, файлы подключались не в той последовательности.

Немного кода

# -*- coding: utf-8 -*-
import settings
from django import forms

class CalendarWidget(forms.TextInput):
    '''
    Данный виджет является, практически, копией
    django.contrib.admin.widgets.AdminDateWidget
    Но наследование от AdminDateWidget не удалось из-за неверного
    порядка JS-файлов в результирующем html, при наследовании.

    Для работы необходимо в urls.py добавить:
    (r'^admin/jsi18n/', 'django.views.i18n.javascript_catalog'),
    '''
    class Media:
        js = ('/admin/jsi18n/',
              settings.ADMIN_MEDIA_PREFIX + 'js/core.js',
              settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
              settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js")
        css = {
            'all': (
                settings.ADMIN_MEDIA_PREFIX + 'css/forms.css',
                settings.ADMIN_MEDIA_PREFIX + 'css/base.css',
                settings.ADMIN_MEDIA_PREFIX + 'css/widgets.css',)
        }

    def __init__(self, attrs={}):
        super(CalendarWidget, self).__init__(attrs={'class': 'vDateField', 'size': '10'})

Вот и весь код, но для корректной работы требуется подключение jsi18nurl.py):

urlpatterns += patterns('',
    (r'^admin/jsi18n/', 'django.views.i18n.javascript_catalog'),
)

Результат

P.S.

Примеры кода с другими реализациями данной задачи приветствуются!



Комментарии (17) на запись «Django widget calendar»

  1. adw0rd MonsterID Icon adw0rd | 10.02.2010 в 22:26

    Спасибо, пригодится в скором времени!

  2. Иван MonsterID Icon Иван | 19.02.2010 в 16:40

    Большое спасибо. Благодаря вам много времени сэкономил.

  3. Евгений MonsterID Icon Евгений | 04.07.2010 в 19:40

    А какую-то специфичную информацию в шаблон добавлять надо?
    Я просто новичек в django, а по вашему методу css и js в рендеринг не вставляются.

  4. Евгений MonsterID Icon Евгений | 04.07.2010 в 19:47

    Вопрос снят. Помогло добавление в шаблон следующих строк

    window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";

    {{profile_form.media}}

    За статью огромное спасибо! Очень пригодилось!

  5. Евгений MonsterID Icon Евгений | 04.07.2010 в 19:50

    Второпях запостил неполную версию, вот рабочий вариант.

    {% load adminmedia %}

    window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";

    {{profile_form.media}}

  6. Larin MonsterID Icon Larin | 04.07.2010 в 19:54

    @Евгений
    Желаю удачи в освоении! )

    Кстати, думаю, вполне можно обойтись просто
    {{profile_form.media}}

    А свое решение вы скорее всего нашли на stackoverflow.com. )))

    Вот еще полезная ссылка.

  7. Евгений MonsterID Icon Евгений | 04.07.2010 в 20:01

    @Larin

    Не вышло обойтись, иначе иконка календарика не отрисуется. Хотя я догадываюсь, что мой метод научного тыка до добра не доведет.

  8. Larin MonsterID Icon Larin | 04.07.2010 в 20:05

    Евгений, статью писал давно и по памяти, возможно что-то упустил, и Вы исправили мою оплошность. А возможно у Ваш в коде что-то не так. Как появится время я обязательно проверю данный пример и потом отпишусь.

  9. Евгений MonsterID Icon Евгений | 04.07.2010 в 20:17

    @Larin
    Я и не думал критиковать, статья очень полезная. Просто оставил комментарий на случай, если кто-то столкнется с похожими трудностями. А гугл выдает статью одним из первых результатов, потому есть вероятность, что сюда еще придут люди.

  10. Larin MonsterID Icon Larin | 04.07.2010 в 20:34

    Евгений,я разве что-то сказал о критике? ))) Я сказал, что все мы люди и можем ошибаться ) И я, и вы )
    И как только появится время, я попытаюсь выйснить, чей пример работоспособен. Может оказаться, что оба примера рабочие )

  11. ivankin MonsterID Icon ivankin | 06.09.2010 в 09:32

    День добрый!
    Я правильно понимаю, что Ваш виджет используется так:
    datein = forms.DateField(label=”Начало тура”, widget=CalendarWidget)

    Проделал всё что описанно в Вашей статье, но результата так и не добился. Есть ли возможность более подробно описать использование Вашего виджета?

  12. Larin MonsterID Icon Larin | 06.09.2010 в 10:11

    А какие ошибки?
    Какие js-ники запрашиваются? В общем больше информации из FireBug-а! )
    Все выводы лучше выложите на http://s-c.me/

  13. ivankin MonsterID Icon ivankin | 06.09.2010 в 10:17

    Спасибо за ответ! FireBug’ом как раз и увидел, что js и css не подгрузились… Но! ‘class’: ‘vDateField’, ’size’: ‘10′ применяются. Т.е. поле получило этот класс и размер.

    Вот мой urls.py на всякий случай:

    Copy Source | Copy HTML# urls.py
     
    urlpatterns = patterns(”,
        (r’^admin/filebrowser/’, include(’filebrowser.urls’)),
        (r’^admin/jsi18n/’, ‘django.views.i18n.javascript_catalog’),
        (r’^admin/’, include(admin.site.urls)),
    )

  14. Larin MonsterID Icon Larin | 06.09.2010 в 10:32

    Ну раз поле получило необходимые атрибуты, значит виджет сработал.
    А вот статика не отдается…
    Есть ли в urls.py нечто похожее?

    
    urlpatterns += patterns('',
        (r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
    )
    

    И в settings.py?

    
    PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
    MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media')
    MEDIA_URL = '/media/'
    ADMIN_MEDIA_PREFIX = '/admin/media/'
    

    Почитайте материалы по поводу отдачи статических файлов на dev-сервере.

  15. ivankin MonsterID Icon ivankin | 06.09.2010 в 10:45

    Странно это очень… Потому что любая другая статика отдаётся… Попробывал через shell:

    >>> from content.forms import CalendarWidget
    >>> w = CalendarWidget()
    >>> w.media

    итд… т.е. адекватный вывод…

    получается, что class Media вообще не выполняется … хм

  16. ivankin MonsterID Icon ivankin | 06.09.2010 в 10:47

    можно удалить предыдущее сообщение, т.к. не правильно вставил…


    Copy Source | Copy HTML<link href=”http://localhost:8000/admin_media/css/forms.css” type=”text/css” media=”all” rel=”stylesheet” />
    <link href=”http://localhost:8000/admin_media/css/base.css” type=”text/css” media=”all” rel=”stylesheet” />
    <link href=”http://localhost:8000/admin_media/css/widgets.css” type=”text/css” media=”all” rel=”stylesheet” />
    <script type=”text/javascript” src=”/admin/jsi18n/”></script>
    <script type=”text/javascript” src=”http://localhost:8000/admin_media/js/core.js”></script>
    <script type=”text/javascript” src=”http://localhost:8000/admin_media/js/calendar.js”></script>
    <script type=”text/javascript” src=”http://localhost:8000/admin_media/js/admin/DateTimeShortcuts.js”></script>
     

  17. Larin MonsterID Icon Larin | 06.09.2010 в 10:49

    Прочтите внимательно, обсуждения выше. И все станет понятно )

Оставить комментарий


Copyright, 1983 – 2010