Form Assets (the Media class) 阅读笔记

来源:互联网 发布:淘宝客招募怎么写 编辑:程序博客网 时间:2024/06/05 00:43

Form Assets (the Media class)

Rendering an attractive and easy-to-use Web form requires more than just HTML - it also requires CSS stylesheets, and if you want to use fancy “Web2.0” widgets, you may also need to include some JavaScript on each page. The exact combination of CSS and JavaScript that is required for any given page will depend upon the widgets that are in use on that page.

★ 渲染一个有吸引力并易于应用的 Web form 不仅仅需要 HTML,还需要 CSS。如果你欲使用 Web2.0 widgets,你或许也会需要一些 JavaScript。如果 widgets 在页面被使用,需要结合 CSS 和 JavaScript 

This is where asset definitions come in. Django allows you to associate different files – like stylesheets and scripts – with the forms and widgets that require those assets. For example, if you want to use a calendar to render DateFields, you can define a custom Calendar widget. This widget can then be associated with the CSS and JavaScript that is required to render the calendar. When the Calendar widget is used on a form, Django is able to identify the CSS and JavaScript files that are required, and provide the list of file names in a form suitable for easy inclusion on your Web page.  ★ 

Assets and Django Admin

The Django Admin application defines a number of customized widgets for calendars, filtered selections, and so on. These widgets define asset requirements, and the Django Admin uses the custom widgets in place of the Django defaults. The Admin templates will only include those files that are required to render the widgets on any given page.

If you like the widgets that the Django Admin application uses, feel free to use them in your own application! They’re all stored in django.contrib.admin.widgets.

★ Django Admin app 为calendars,filtered selections 等等定义了一系列定制的 widgets。这些 widgets 定义优势需求,Django Admin 在 Django 默认的地方使用定制的widgets。Admin 模板仅仅包含那些被要求渲染widgets或给定的page的文件。如果你喜欢 Django Admin app 使用的widgets,尽情地在你的app里使用它们。它们存放在 django.contrib.admin.widgets 里 

Which JavaScript toolkit?

Many JavaScript toolkits exist, and many of them include widgets (such as calendar widgets) that can be used to enhance your application. Django has deliberately avoided blessing any one JavaScript toolkit. Each toolkit has its own relative strengths and weaknesses - use whichever toolkit suits your requirements. Django is able to integrate with any JavaScript toolkit.

★ 有很多 JavaScript 小工具,其中很多包含了 widgets(比如 calendar widgets),这些 widgets 可以被用来强化你的app。Django 小心的避免依赖于特定的 JavaScript 小工具。每个js工具有它自己的优点和缺点。Django 能够和任何的 JavaScript 工具进行整合 

Assets as a static definition

The easiest way to define assets is as a static definition. Using this method, the declaration is an inner Media class. The properties of the inner class define the requirements.

Here’s a simple example:  ★ 最简单定义 Assets 的方式是引用静态css和js。使用内部类 Media

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

This code defines a CalendarWidget, which will be based on TextInput. Every time the CalendarWidget is used on a form, that form will be directed to include the CSS file pretty.css, and the JavaScript files animations.js and actions.js.  ★ 会使用 STATIC_URL 里的这几个css和js文件 

This static definition is converted at runtime into a widget property named media. The list of assets for a CalendarWidget instance can be retrieved through this property:

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

Here’s a list of all possible Media options. There are no required options.

css

A dictionary describing the CSS files required for various forms of output media.  ★ 一个字典,定义了 各种 CSS 文件 

The values in the dictionary should be a tuple/list of file names. See the section on paths for details of how to specify paths to these files.  ★ 此字典的“值“必须是tuple或list

The keys in the dictionary are the output media types. These are the same types accepted by CSS files in media declarations: ‘all’, ‘aural’, ‘braille’, ‘embossed’, ‘handheld’, ‘print’, ‘projection’, ‘screen’, ‘tty’ and ‘tv’. If you need to have different stylesheets for different media types, provide a list of CSS files for each output medium. The following example would provide two CSS options – one for the screen, and one for print:  ★ 字典里的”键“是 css 的 media 类型,包括 ‘all’, ‘aural’, ‘braille’, ‘embossed’, ‘handheld’, ‘print’, ‘projection’, ‘screen’, ‘tty', ‘tv’ 

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

If a group of CSS files are appropriate for multiple output media types, the dictionary key can be a comma separated list of output media types. In the following example, TV’s and projectors will have the same media requirements:  ★ “字典 - 键” 可以被逗号分隔 

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

If this last CSS definition were to be rendered, it would become the following 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

 A tuple describing the required JavaScript files. See the section on paths for details of how to specify paths to these files.   ★ 一个元组,描述了需要的 JavaScript 

extend

A boolean defining inheritance behavior for Media declarations.  ★ 一个布尔值,定义 Media 的继承行为 

By default, any object using a static Media definition will inherit all the assets associated with the parent widget. This occurs regardless of how the parent defines its own requirements. For example, if we were to extend our basic Calendar widget from the example above:  ★ 默认,任何静态定义 Media 的对象都会继承和父 widget 相关联的控件。

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

The FancyCalendar widget inherits all the assets from its parent widget. If you don’t want Media to be inherited in this way, add an extend=False declaration to the Media declaration:

★ 以上,FancyCalendar widget 会继承所有来自父 widget 的前台文件,如果想不继承来自父类的文件,在 Media 里添加 extend=False 

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

If you require even more control over inheritance, define your assets using a dynamic property. Dynamic properties give you complete control over which files are inherited, and which are not.

Media as a dynamic property

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.

★ 可以通过定义一个返回 forms.Media 的 widget 属性,来更精确的实现某些行为。forms.Media 的接收参数的形式和静态定义 media 一样,例子如下。 

For example, the static definition for our Calendar Widget could also be defined in a dynamic fashion:

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

See the section on Media objects for more details on how to construct return values for dynamic media properties.

Paths in asset definitions

Paths used to specify assets can be either relative or absolute. If a path starts with /http:// or https://, it will be interpreted as an absolute path, and left as-is. All other paths will be prepended with the value of the appropriate prefix.  ★ 定义了路径可以是相对路径,也可以是绝对路径。当路径以 /, http:// 或 https:// 开始时,是绝对路径 

As part of the introduction of the staticfiles app two new settings were added to refer to “static files” (images, CSS, Javascript, etc.) that are needed to render a complete web page: STATIC_URL and STATIC_ROOT.  ★ 为了引用静态文件(例如,图片,CSS,Javascript 等等),需要设置两个东西:STATIC_URL 和 STATIC_ROOT 

To find the appropriate prefix to use, Django will check if the STATIC_URL setting is not None and automatically fall back to using MEDIA_URL. For example, if the MEDIA_URL for your site was 'http://uploads.example.com/' and STATIC_URL was None:  ★ Django 先检查 STATIC_URL 是否存在要求文件,不存在则在 MEDIA_URL 里检查 

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

But if STATIC_URL is '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 objects

When you interrogate the media attribute of a widget or form, the value that is returned is a forms.Media object. As we have already seen, the string representation of a Media object is the HTML required to include the relevant files in the <head> block of your HTML page.

However, Media objects have some other interesting properties.

Subsets of assets

If you only want files of a particular type, you can use the subscript operator to filter out a medium of interest. For example:  ★ 如果仅要得到某种类型,可以用特定的关键字过滤 

>>> 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" />

When you use the subscript operator, the value that is returned is a new Media object – but one that only contains the media of interest.

Combining Media objects

Media objects can also be added together. When two Media objects are added, the resulting Media object contains the union of the assets specified by both:

★ 两个 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 on Forms

Widgets aren’t the only objects that can have media definitions – forms can also define media. The rules for media definitions on forms are the same as the rules for widgets: declarations can be static or dynamic; path and inheritance rules for those declarations are exactly the same.

★ 不但在 widgets 上可以定义 media,在 forms 里也可以定义 media;两者的规则都一样:静态定义文件,路径的规则,继承的规则

Regardless of whether you define a media declaration, all Form objects have a media property. The default value for this property is the result of adding the media definitions for all widgets that are part of the form:  ★ 无论是否声明了 media,所有 Form 对象都由一个 media 属性。media 默认值是添加所有 form 中 fields 对应的 widgets 的 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>

If you want to associate additional assets with a form – for example, CSS for form layout – simply add a Media declaration to the form:

>>> 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>
0 0
原创粉丝点击