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('\n'.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的引用。javascript

屬性self._js = [], self._css = {} 分別負責js和css的文件引用。css

方法add_js,add_css負責添加文件引用。html

方法render_js, render_css負責輸出引用js和css的html語句。java


經過對add_js(self,  data)方法的分析, 能夠看出參數data的格式是['js_path_1', 'js_path_2']。self._js的格式也是由js文件名組成的列表。python

經過對add_css(self, data)方法的分析, 能夠看參數data的格式爲app

{'medium_type_1': ['type_1_path_1', 'type_1_path_2',....], url

'medium_type_2': ['type_2_path_1', ...]code

....}。orm

self._css的格式也是由medium:paths組成的字典。paths是由path組成的列表。htm


經過調用方法的形式,

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)})
本站公眾號
   歡迎關注本站公眾號,獲取更多信息