Spec-Zone.ru › Django 1.8

Формы Аксессуары (класс Media)

Для визуального оформления и удобного использования веб-формы необходимо не только HTML, но и CSS-стили, а если вы хотите использовать продвинутые виджеты «Web2.0», то вам, возможно, потребуется включить JavaScript на каждой странице. Точный набор CSS и JavaScript, необходимый для каждой конкретной страницы, будет зависеть от используемых на ней виджетов.

Здесь на помощь приходят определения активов. Django позволяет связывать различные файлы — такие как таблицы стилей и скрипты — с формами и виджетами, которым требуются эти активы. Например, если вы хотите использовать календарь для отображения полей типа DateField, вы можете определить пользовательский виджет Calendar. Этот виджет затем можно связать с CSS и JavaScript, необходимыми для отображения календаря. Когда виджет Calendar используется в форме, Django может определить необходимые CSS и JavaScript-файлы и предоставить список имён файлов в формате, удобном для лёгкой вставки на вашу веб-страницу.

Аксессуары и Django Admin

Приложение Django Admin определяет ряд настраиваемых виджетов для календарей, фильтрованных выборов и т. д. Эти виджеты определяют требования к активам, и Django Admin использует пользовательские виджеты вместо стандартных Django. Шаблоны Admin будут включать только те файлы, которые необходимы для отображения виджетов на данной странице.

Если вам нравятся виджеты, используемые приложением Django Admin, вы можете использовать их и в своём приложении! Они все хранятся в django.contrib.admin.widgets.

Какой JavaScript-фреймворк?

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

Аксессуары как статическое определение

Самый простой способ определения активов — это статическое определение. Используя этот метод, объявление представляет собой внутренний Media класс. Свойства внутреннего класса определяют требования.

Вот простой пример:

from django import forms

class CalendarWidget(forms.TextInput):
    class Media:
        css = {
            'all': ('pretty.css',)
        }
        js = ('animations.js', 'actions.js')

Этот код определяет CalendarWidget, который будет основан на TextInput. Каждый раз, когда виджет Calendar используется в форме, эта форма будет включена в CSS-файл pretty.css, и JavaScript-файлы animations.js и actions.js.

Это статическое определение в процессе выполнения преобразуется в свойство виджета под названием media. Список активов для экземпляра CalendarWidget можно получить через это свойство:

>>> w = CalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>

Вот список всех возможных Media параметров. Требуемых параметров нет.

css

Словарь, описывающий необходимые CSS-файлы для различных типов вывода.

Значения в словаре должны быть кортежем/списком имён файлов. Подробности о том, как указать пути к этим файлам, см. в разделе пути.

Ключи в словаре — типы вывода. Это те же типы, что и в объявлениях CSS в декларациях media: 'all', 'aural', 'braille', 'embossed', 'handheld', 'print', 'projection', 'screen', 'tty' и 'tv'. Если вам нужны разные таблицы стилей для разных типов вывода, укажите список CSS-файлов для каждого типа вывода. Следующий пример предоставляет два варианта CSS — один для экрана и один для печати:

class Media:
    css = {
        'screen': ('pretty.css',),
        'print': ('newspaper.css',)
    }

Если набор CSS-файлов подходит для нескольких типов вывода, ключ словаря может быть запятой, разделённым списком типов вывода. В следующем примере требования к медиа будут одинаковыми для телевизоров и проекторов:

class Media:
    css = {
        'screen': ('pretty.css',),
        'tv,projector': ('lo_res.css',),
        'print': ('newspaper.css',)
    }

Если это последнее определение CSS будет отрисовано, оно преобразуется в следующий HTML:

<link href="http://static.example.com/pretty.css" type="text/css" media="screen" rel="stylesheet" />
<link href="http://static.example.com/lo_res.css" type="text/css" media="tv,projector" rel="stylesheet" />
<link href="http://static.example.com/newspaper.css" type="text/css" media="print" rel="stylesheet" />

js

Кортеж, описывающий необходимые JavaScript-файлы. Подробности о том, как указать пути к этим файлам, см. в разделе пути.

extend

Булево значение, определяющее поведение наследования для Media деклараций.

По умолчанию любой объект, использующий статическое Media определение, наследует все активы, связанные с родительским виджетом. Это происходит независимо от того, как родитель определяет свои собственные требования. Например, если мы должны расширить наш базовый виджет Calendar из примера выше:

>>> class FancyCalendarWidget(CalendarWidget):
...     class Media:
...         css = {
...             'all': ('fancy.css',)
...         }
...         js = ('whizbang.js',)

>>> w = FancyCalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<link href="http://static.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

Виджет FancyCalendar наследует все активы от родительского виджета. Если вы не хотите, чтобы Media наследовались таким образом, добавьте объявление extend=False в объявление Media.

>>> class FancyCalendarWidget(CalendarWidget):
...     class Media:
...         extend = False
...         css = {
...             'all': ('fancy.css',)
...         }
...         js = ('whizbang.js',)

>>> w = FancyCalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

Если вам нужен более тонкий контроль над наследованием, определите свои активы, используя динамическое свойство. Динамические свойства обеспечивают полный контроль над тем, какие файлы наследуются, а какие нет.

Media как динамическое свойство

Если вам необходимо выполнить более сложные манипуляции с требованиями к активам, вы можете определить свойство media напрямую. Это делается путём определения свойства виджета, которое возвращает экземпляр forms.Media. Конструктор forms.Media принимает css и js ключевые аргументы в том же формате, что и статическое определение медиа.

Например, статическое определение нашего виджета Calendar также можно определить динамическим способом:

class CalendarWidget(forms.TextInput):
    def _media(self):
        return forms.Media(css={'all': ('pretty.css',)},
                           js=('animations.js', 'actions.js'))
    media = property(_media)

См. раздел объекты Media для получения более подробной информации о том, как создавать возвращаемые значения для динамических media свойств.

Пути в определениях активов

Пути, используемые для указания активов, могут быть относительными или абсолютными. Если путь начинается с /, http:// или https://, он будет интерпретироваться как абсолютный путь и останется неизменным. Все остальные пути будут дополнены значением соответствующего префикса.

В рамках введения приложения staticfiles были добавлены две новые настройки для ссылок на «статические файлы» (изображения, CSS, JavaScript и т. д.), необходимые для отображения полной веб-страницы: STATIC_URL и STATIC_ROOT.

Чтобы определить соответствующий префикс, Django проверит, не является ли настройка STATIC_URL пустой и автоматически вернётся к использованию MEDIA_URL. Например, если MEDIA_URL для вашего сайта было 'http://uploads.example.com/', а STATIC_URL было None, то:

>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
...     class Media:
...         css = {
...             'all': ('/css/pretty.css',),
...         }
...         js = ('animations.js', 'http://othersite.com/actions.js')

>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://uploads.example.com/animations.js"></script>
<script type="text/javascript" src="http://othersite.com/actions.js"></script>

Но если STATIC_URL равно 'http://static.example.com/', то:

>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://othersite.com/actions.js"></script>

Media объекты

При обращении к атрибуту media виджета или формы возвращается объект forms.Media. Как мы уже видели, строковое представление объекта Media — это HTML, необходимый для включения соответствующих файлов в блок <head> вашей HTML-страницы.

Однако объекты Media имеют и другие интересные свойства.

Подмножества активов

Если вы хотите только файлы определённого типа, вы можете использовать оператор подстроки для фильтрации интересующего вас типа медиа. Например:

>>> w = CalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>

>>> print(w.media['css'])
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />

При использовании оператора подстроки возвращается новый объект Media — но только содержащий интересующее вас медиа.

Комбинирование Media объектов

Объекты Media также могут складываться. Когда два объекта Media складываются, получившийся объект Media содержит объединение активов, указанных в обоих:

>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
...     class Media:
...         css = {
...             'all': ('pretty.css',)
...         }
...         js = ('animations.js', 'actions.js')

>>> class OtherWidget(forms.TextInput):
...     class Media:
...         js = ('whizbang.js',)

>>> w1 = CalendarWidget()
>>> w2 = OtherWidget()
>>> print(w1.media + w2.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

Media в формах

Виджеты не единственные объекты, которые могут иметь media определения — формы также могут иметь media. Правила media определений для форм такие же, как и для виджетов: объявления могут быть статическими или динамическими; правила путей и наследования для этих объявлений точно такие же.

Независимо от того, определяете ли вы объявление media, все объекты формы имеют свойство media. Значение по умолчанию для этого свойства — результат сложения media определений всех виджетов, входящих в форму:

>>> from django import forms
>>> class ContactForm(forms.Form):
...     date = DateField(widget=CalendarWidget)
...     name = CharField(max_length=40, widget=OtherWidget)

>>> f = ContactForm()
>>> f.media
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

Если вы хотите связать дополнительные активы с формой — например, CSS для макета формы — просто добавьте объявление Media в форму:

>>> class ContactForm(forms.Form):
...     date = DateField(widget=CalendarWidget)
...     name = CharField(max_length=40, widget=OtherWidget)
...
...     class Media:
...         css = {
...             'all': ('layout.css',)
...         }

>>> f = ContactForm()
>>> f.media
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<link href="http://static.example.com/layout.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.8/topics/forms/media/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API