Форма Assets ( Media
класс) ¶
Визуализация привлекательной и простой в использовании веб-формы требует большего, чем просто HTML - для этого также требуются таблицы стилей CSS, и если вы хотите использовать причудливые виджеты «Web2.0», вам также может потребоваться включить некоторый JavaScript на каждую страницу. Точная комбинация CSS и JavaScript, которая требуется для любой данной страницы, будет зависеть от виджетов, которые используются на этой странице.
Здесь на помощь приходят определения ресурсов. Django позволяет вам связывать различные файлы - например, таблицы стилей и скрипты - с формами и виджетами, которым требуются эти ресурсы. Например, если вы хотите использовать календарь для отображения DateFields, вы можете определить собственный виджет «Календарь». Затем этот виджет можно связать с CSS и JavaScript, которые необходимы для визуализации календаря. Когда виджет «Календарь» используется в форме, Django может определить необходимые файлы CSS и JavaScript и предоставить список имен файлов в форме, подходящей для включения на вашу веб-страницу.
Активы и администратор Django
Приложение Django Admin определяет ряд настраиваемых виджетов для календарей, отфильтрованного выбора и так далее. Эти виджеты определяют требования к ресурсам, а администратор Django использует настраиваемые виджеты вместо значений по умолчанию для Django. Шаблоны администратора будут включать только те файлы, которые необходимы для отображения виджетов на любой данной странице.
Если вам нравятся виджеты, которые использует приложение 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
. Каждый раз, когда 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 в объявлениях мультимедиа: 'all', 'aural', 'braille', 'embossed', 'handheld', 'print', 'projection', 'screen', 'tty' и ' Телевизор'. Если вам нужно иметь разные таблицы стилей для разных типов мультимедиа, предоставьте список файлов 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
определение, наследует все активы, связанные с родительским виджетом. Это происходит независимо от того, как родитель определяет свои собственные требования. Например, если бы мы расширили наш базовый виджет Календаря из приведенного выше примера:
>>> 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
определений в формах такие же, как и для виджетов: объявления могут быть статическими или динамическими; правила пути и наследования для этих объявлений точно такие же.
Независимо от того, определяете ли вы 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>