Файлы вспомогательных форм (класс Media )

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

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

Вспомогательные файлы в администрировании Django

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

Если вам нравятся компоненты, используемые сайтом администратора Django, вы можете свободно использовать их в своем приложении! Они внутри 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 . Каждый раз, когда CalendarWidget он будет использоваться в форме, последняя должна будет включать файл 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 src="http://static.example.com/animations.js"></script>
<script 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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
<script 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 src="http://static.example.com/whizbang.js"></script>

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

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

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

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

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

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

Пути в определениях сторонних файлов

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

Независимо от того, используется приложение django.contrib.staticfiles или нет, настройки STATIC_URL и STATIC_ROOT необходимы для создания полноценной веб-страницы.

Чтобы найти правильный префикс для использования, Django проверяет, STATIC_URL отличается ли этот параметр от None и 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 src="http://uploads.example.com/animations.js"></script>
<script 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 src="http://static.example.com/animations.js"></script>
<script src="http://othersite.com/actions.js"></script>

Или, если staticfiles настроен с хранилищем ManifestStaticFilesStorage :

>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.27e20196a850.js"></script>
<script 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 src="http://static.example.com/animations.js"></script>
<script 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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
<script src="http://static.example.com/whizbang.js"></script>

Порядок дополнительных файлов

Порядок, в котором побочные файлы вставляются в DOM, часто важен. Например, у вас может быть сценарий, зависящий от jQuery. Таким образом, комбинация объектов Media пытается поддерживать относительный порядок, в котором побочные файлы определены в каждом классе Media .

Например :

>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
...     class Media:
...         js = ('jQuery.js', 'calendar.js', 'noConflict.js')
>>> class TimeWidget(forms.TextInput):
...     class Media:
...         js = ('jQuery.js', 'time.js', 'noConflict.js')
>>> w1 = CalendarWidget()
>>> w2 = TimeWidget()
>>> print(w1.media + w2.media)
<script src="http://static.example.com/jQuery.js"></script>
<script src="http://static.example.com/calendar.js"></script>
<script src="http://static.example.com/time.js"></script>
<script src="http://static.example.com/noConflict.js"></script>

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

Media для форм

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

Независимо от того, определяете вы объявление media или нет, у всех объектов Form есть свойство 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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
<script 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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
<script src="http://static.example.com/whizbang.js"></script>

Copyright ©2020 All rights reserved