dajngo.forms.widget-Media
MEDIA_TYPES = ('css', 'js')
class Media(object):
def __init__(self, media=None, **kwargs):
if media:
media_attrs = media.__dict__
else:
media_attrs = kwargs
self._css = {}
self._js = []
for name in MEDIA_TYPES:
getattr(self, 'add_' + name)(media_attrs.get(name, None))
def __str__(self):
return self.render()
def render(self):
return mark_safe('
'.join(chain(*[getattr(self, 'render_' + name)() for name in MEDIA_TYPES])))
def render_js(self):
return [
format_html(
'<script type="text/javascript" src="{0}"></script>',
self.absolute_path(path)
) for path in self._js
]
def render_css(self):
# To keep rendering order consistent, we can't just iterate over items().
# We need to sort the keys, and iterate over the sorted list.
media = sorted(self._css.keys())
return chain(*[[
format_html(
'<link href="{0}" type="text/css" media="{1}" rel="stylesheet" />',
self.absolute_path(path), medium
) for path in self._css[medium]
] for medium in media])
def absolute_path(self, path, prefix=None):
if path.startswith(('http://', 'https://', '/')):
return path
if prefix is None:
if settings.STATIC_URL is None:
# backwards compatibility
prefix = settings.MEDIA_URL
else:
prefix = settings.STATIC_URL
return urljoin(prefix, path)
def __getitem__(self, name):
"Returns a Media object that only contains media of the given type"
if name in MEDIA_TYPES:
return Media(**{str(name): getattr(self, '_' + name)})
raise KeyError('Unknown media type "%s"' % name)
def add_js(self, data):
if data:
for path in data:
if path not in self._js:
self._js.append(path)
def add_css(self, data):
if data:
for medium, paths in data.items():
for path in paths:
if not self._css.get(medium) or path not in self._css[medium]:
self._css.setdefault(medium, []).append(path)
def __add__(self, other):
combined = Media()
for name in MEDIA_TYPES:
getattr(combined, 'add_' + name)(getattr(self, '_' + name, None))
getattr(combined, 'add_' + name)(getattr(other, '_' + name, None))
return combined
Mediaはjsとcssの参照を担当する.
属性self.js = [], self._css={}はjsとcssのファイル参照をそれぞれ担当します.
メソッドadd_js,add_cssはファイルリファレンスの追加を担当します.
メソッドrender_js, render_cssはjsとcssを参照するhtml文の出力を担当します.
add_js(self,data)法の解析から,パラメータdataのフォーマットは['js_path_1','js_path_2']であることが分かった.self._jsのフォーマットもjsファイル名からなるリストです.
add_css(self,data)法の解析から,パラメータdataのフォーマットは
{'medium_type_1': ['type_1_path_1', 'type_1_path_2',....],
'medium_type_2': ['type_2_path_1', ...]
....}.
self._cssのフォーマットもmedium:pathsからなる辞書です.pathsはpathからなるリストです.
メソッドの形式を呼び出すことで、
getattr(self, 'add_' + name),
getattr(self, 'render_' + name)
見ることができるのはすべて
MEDIA_TYPES = ('css', 'js')
名前を付けます.
render()とrender_が見えますcss()はchainメソッドを使用しています.
まずrender_を見てみましょうcss(),
chain(*[[
format_html(
'<link href="{0}" type="text/css" media="{1}" rel="stylesheet" />',
self.absolute_path(path), medium
) for path in self._css[medium]
] for medium in media])
ネストされたリスト式を参照
[[
format_html(
'<link href="{0}" type="text/css" media="{1}" rel="stylesheet" />',
self.absolute_path(path), medium
) for path in self._css[medium]
] for medium in media]
ここではネストされたリストを返します.フォーマットは
[
[ '<link href="path_1" type="text/css" media="medium_type_1" rel="stylesheet" />',
'<link href="path_2" type="text/css" media="medium_type_1" rel="stylesheet" />'
] #medium_type_1
[ '<link href="path_1" type="text/css" media="medium_type_2" rel="stylesheet" />',
'<link href="path_2" type="text/css" media="medium_type_2" rel="stylesheet" />'
] #medium_type_2
...
]
それからchain(*lists)を使って、*伝参を使って、chainの比較的によく使う技巧です.
render()メソッドのchain呼び出しも、同じです
最後にMediaの使用の流れについてお話しします.
初期化
def __init__(self, media=None, **kwargs):
mediaパラメータを優先し、次にkwargsパラメータを使用します.
これらのパラメータは、これらのプロパティのみで有用であることもわかります.
MEDIA_TYPES = ('css', 'js')
これらのフォーマットはadd_に適合する必要がありますjs()とadd_css()のパラメータdataフォーマット.
add_の使用js()とadd_css()ファイルパスを追加します.
render_の使用js()とrender_css(),render()html文を出力します.
注意absolute_path(self,path,prefix=None)メソッド、
pathには特別な要求がある.
jsとcssの取得
__getitem__(self, name):
辞書で手に入れることができます新しいmeidaインスタンスを返します.
return Media(**{str(name): getattr(self, '_' + name)})