表单资源( Media 类) — Django 6.0.4 documentation(2026)
创始人
2026-06-01 21:20:37
0
Django教程

表单资源( Media 类)

呈现一个有吸引力的、易于使用的网络表格需要的不仅仅是 HTML,它还需要 CSS 样式表,如果你想使用花哨的部件,你可能还需要在每个页面上包含一些 JavaScript。任何特定页面所需的 CSS 和 JavaScript 的确切组合将取决于该页面上使用的部件。

这就是资源定义的作用。Django 允许你将不同的文件——如样式表和脚本——与需要这些资产的表单和部件联系起来。例如,如果你想用一个日历来渲染 DateFields,你可以定义一个自定义的日历部件。然后这个部件可以与渲染日历所需的 CSS 和 JavaScript 相关联。当日历部件在表单上使用时,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 。每次CalendarWidget在表单上使用时,该表单都会包含CSS文件 pretty.css ,以及JavaScript文件 animations.jsactions.js

这个静态定义在运行时被转换为一个名为 media 的小部件属性。可以通过这个属性获取 CalendarWidget 实例的资产列表:

>>> w = CalendarWidget()
>>> print(w.media)



以下是所有可能的 Media 选项列表。没有一个是必需项。

css

描述各种表单输出媒体所需的CSS文件的字典。

字典中的值应该是一个文件名元组/列表。有关如何指定这些文件的路径的详细内容,请参阅 路径章节

字典中的键是输出媒体类型。它们和媒体声明中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文件的一个元组。有关如何指定这些文件的路径的详细内容,请参阅 路径章节

Script objects

New in Django 5.2.
class Script(src, **attributes)[source]

Represents a script file.

The first parameter, src, is the string path to the script file. See the section on paths for details on how to specify paths to these files.

The optional keyword arguments, **attributes, are HTML attributes that are set on the rendered

FancyCalendar 小部件继承了其父级小部件的所有资产。如果你不希望 Media 以这种方式被继承,可以在 Media 声明中添加一个 extend=False 声明:

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

>>> w = FancyCalendarWidget()
>>> print(w.media)


如果您需要更多的继承控制,用一个 动态属性 定义你的 。动态属性使您可以完全控制哪些文件是否继承。

Media 作为动态属性

If you need to perform some more sophisticated manipulation of asset requirements, you can define the media property directly. This is done by defining a widget property that returns an instance of forms.Media. The constructor for forms.Media accepts css and js keyword arguments in the same format as that used in a static media definition.

例如,我们也可以以动态的方式定义日历组件的静态定义:

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_URLSTATIC_ROOT 来渲染一张完整的网页。

为了找到要使用的前缀,Django 会检查 STATIC_URL 设置是否不为 None,并自动回退到使用 MEDIA_URL。例如,如果你的站点的 MEDIA_URL'https://uploads.example.com/'STATIC_URLNone

>>> 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)



但如果 STATIC_URL'https://static.example.com/'

>>> w = CalendarWidget()
>>> print(w.media)



或者如果使用 ManifestStaticFilesStorage 配置了 staticfiles

>>> w = CalendarWidget()
>>> print(w.media)



路径作为对象

Assets may also be object-based, using Script. Furthermore, these allow you to pass custom HTML attributes:

class Media:
    js = [
        Script(
            "https://cdn.example.com/something.min.js",
            **{
                "crossorigin": "anonymous",
                "async": True,
            },
        ),
    ]

If this Media definition were to be rendered, it would become the following HTML:

<script src="https://cdn.example.com/something.min.js"
        crossorigin="anonymous"
        async>
script>
Changed in Django 5.2:

The object class Script was added.

Media 对象

当您访问表单或者组件的 media 属性时,返回值是一个 forms.Media 对象。正如我们已经看到的, Media 对象的字符串表示是一段需要在您HTML页面的 块中包含相关文件的HTML代码。

然而, Media 对象还有其他一些有趣的属性。

资源的子集

如果你只想要特定类型的文件,你可以使用下标运算符来过滤出感兴趣的媒体。例如:

>>> w = CalendarWidget()
>>> print(w.media)




>>> print(w.media["css"])

当您使用下标运算符时,返回值是一个新的 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)




资源的排序

资源插入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)




合并 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




如果你想将额外的资产与一个表单关联起来,例如,表单布局的 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





Last update:

4月 20, 2026


本文整理自 Django 6.0 官方中文文档,转载请注明出处。

相关内容

热门资讯

玻璃硬盘原理图 玻璃硬盘原理 玻璃硬盘,又称为磁头悬浮硬盘(Magnetic Head Flying Disk,MHFD),是一种...
闲鱼搜索规则与技巧 闲鱼最新特... 在闲鱼这个二手交易平台上,有很多用户都希望能够找到一些特殊的东西,比如一些罕见的收藏品、独特的手工艺...
家里监控最长能保存多少天的记录... 家里监控一般保存多久 随着科技的发展,家庭监控系统已经成为了许多家庭的必备设备,它不仅可以帮助我们...
华为tag有用吗 华为tag-... 华为Tag是华为手机中的一种功能,它可以帮助用户更好地管理自己的手机数据和应用,通过使用华为Tag,...
ps5手柄可用手机快充充电吗 ... PS5手柄,即PlayStation 5的DualSense手柄,是索尼公司为PlayStation...
QQ音乐提示代理模式可能无法正... QQ音乐提示代理模式可能无法正常访问,如上图所示,是怎么回事呢? 这个可能和你的网络设置有关系,首先...
收到微信有提示音怎么去掉 微信... 微信收到信息没有提示音,可能是由多种原因导致的,以下是一些可能的原因及解决方法: 1. 手机静音或...
a100显卡对应的cuda版本 在进行GPU加速的编程中,CUDA是常用的架构和平台,其版本和显卡型号之间存在着一定的对应关系。本篇...
别人打电话听不见我说话怎么回事... 当我们在使用手机时,可能会遇到别人打电话过来听不见声音的情况,这种情况可能是由多种原因导致的,下面我...
苹果手机非通讯录电话打不进来 ... 手机电话打不进来可能有多种原因,以下是一些常见的问题及解决方法: 1. **信号问题**: ...