Media
类)¶呈现一个有吸引力且易于使用的Web表单需要的不仅仅是HTML--它还需要CSS样式表,如果您想要使用奇特的小部件,您可能还需要在每个页面上包含一些JavaScript。任何给定页面所需的CSS和JavaScript的确切组合将取决于该页面上使用的小部件。
这就是资产定义发挥作用的地方。Django允许您将不同的文件--如样式表和脚本--与需要这些资产的表单和小部件相关联。例如,如果您想要使用日历来呈现DateFields,您可以定义一个定制的Calendar小部件。然后,可以将此小部件与呈现日历所需的CSS和JavaScript相关联。当在表单上使用Calendar小部件时,Django能够识别所需的CSS和JavaScript文件,并以适合包含在您的Web页面上的形式提供文件名列表。
资产和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="https://static.example.com/pretty.css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.js"></script>
<script src="https://static.example.com/actions.js"></script>
这是所有可能的列表 Media
选项。没有必需的选项。
css
¶描述各种输出媒体所需的CSS文件的字典。
字典中的值应该是文件名的元组/列表。见 the section on paths 有关如何指定这些文件的路径的详细信息。
字典中的键是输出媒体类型。这些类型与CSS文件在媒体声明中接受的类型相同:“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="https://static.example.com/pretty.css" media="screen" rel="stylesheet">
<link href="https://static.example.com/lo_res.css" media="tv,projector" rel="stylesheet">
<link href="https://static.example.com/newspaper.css" media="print" rel="stylesheet">
js
¶描述所需JavaScript文件的元组。见 the section on paths 有关如何指定这些文件的路径的详细信息。
extend
¶为定义继承行为的布尔值 Media
声明。
默认情况下,任何使用静态 Media
定义将继承与父小部件相关联的所有资产。无论父级如何定义自己的需求,都会发生这种情况。例如,如果我们要扩展上面示例中的基本日历小部件:
>>> class FancyCalendarWidget(CalendarWidget):
... class Media:
... css = {
... "all": ["fancy.css"],
... }
... js = ["whizbang.js"]
...
>>> w = FancyCalendarWidget()
>>> print(w.media)
<link href="https://static.example.com/pretty.css" media="all" rel="stylesheet">
<link href="https://static.example.com/fancy.css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.js"></script>
<script src="https://static.example.com/actions.js"></script>
<script src="https://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="https://static.example.com/fancy.css" media="all" rel="stylesheet">
<script src="https://static.example.com/whizbang.js"></script>
如果您需要对继承进行更多的控制,请使用 dynamic property . 动态属性使您可以完全控制哪些文件是继承的,哪些文件不是继承的。
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 objects 有关如何构造动态的返回值的详细信息 media
性质。
用于指定资源的字符串路径可以是相对路径,也可以是绝对路径。如果路径以 /
, http://
或 https://
,它将被解释为绝对路径,并按原样保留。所有其他路径都将使用相应前缀的值作为前缀。如果 django.contrib.staticfiles
应用程序已安装,它将用于服务资产。
是否使用 django.contrib.staticfiles
, the STATIC_URL
和 STATIC_ROOT
需要设置才能呈现完整的网页。
为了找到要使用的适当前缀,Django将检查 STATIC_URL
设置不是 None
并自动回退到使用 MEDIA_URL
。例如,如果 MEDIA_URL
因为你的网站是 'https://uploads.example.com/'
和 STATIC_URL
曾经是 None
:
>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
... class Media:
... css = {
... "all": ["/css/pretty.css"],
... }
... js = ["animations.js", "https://othersite.com/actions.js"]
...
>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" media="all" rel="stylesheet">
<script src="https://uploads.example.com/animations.js"></script>
<script src="https://othersite.com/actions.js"></script>
但如果 STATIC_URL
是 'https://static.example.com/'
:
>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.js"></script>
<script src="https://othersite.com/actions.js"></script>
或者如果 staticfiles
是使用 ManifestStaticFilesStorage
:
>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.27e20196a850.js"></script>
<script src="https://othersite.com/actions.js"></script>
资源路径也可以作为可散列对象提供,实现 __html__()
方法。这个 __html__()
方法通常使用 html_safe()
装饰师。该对象负责输出完整的HTML <script>
或 <link>
标签内容:
>>> from django import forms
>>> from django.utils.html import html_safe
>>>
>>> @html_safe
... class JSPath:
... def __str__(self):
... return '<script src="https://example.org/asset.js" defer>'
...
>>> class SomeWidget(forms.TextInput):
... class Media:
... js = [JSPath()]
...
Media
对象¶当你审问 media
小部件或窗体的属性,返回的值是 forms.Media
对象。正如我们已经看到的,字符串表示 Media
对象是将相关文件包含在 <head>
阻止HTML页。
然而, Media
对象还有一些其他有趣的属性。
如果只需要特定类型的文件,可以使用下标操作符筛选出感兴趣的介质。例如:
>>> w = CalendarWidget()
>>> print(w.media)
<link href="https://static.example.com/pretty.css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.js"></script>
<script src="https://static.example.com/actions.js"></script>
>>> print(w.media["css"])
<link href="https://static.example.com/pretty.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="https://static.example.com/pretty.css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.js"></script>
<script src="https://static.example.com/actions.js"></script>
<script src="https://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="https://static.example.com/jQuery.js"></script>
<script src="https://static.example.com/calendar.js"></script>
<script src="https://static.example.com/time.js"></script>
<script src="https://static.example.com/noConflict.js"></script>
结合 Media
具有冲突顺序的资产的对象会导致 MediaOrderConflictWarning
.
Media
形式上¶小部件不是唯一可以拥有的对象 media
定义——表单还可以定义 media
. 规则 media
窗体上的定义与小部件的规则相同:声明可以是静态的或动态的;这些声明的路径和继承规则完全相同。
不管您是否定义了 media
声明, all 表单对象有一个 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="https://static.example.com/pretty.css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.js"></script>
<script src="https://static.example.com/actions.js"></script>
<script src="https://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="https://static.example.com/pretty.css" media="all" rel="stylesheet">
<link href="https://static.example.com/layout.css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.js"></script>
<script src="https://static.example.com/actions.js"></script>
<script src="https://static.example.com/whizbang.js"></script>
7月 22, 2024