Django模板(包含带媒体的表单)包含类似下面的代码片段,当使用带有COMPRESS_OFFLINE=True
的django-compressor时会抛出错误,因为当离线压缩时form
不可用执行:
# Template snippet
{% compress js %}
{{ form.media.js }}
{% endcompress %}
一般来说,django-compressor提供COMPRESS_OFFLINE_CONTEXT设置来处理类似的情况。但是,如果网站包含许多此类表格或小部件与媒体,此解决方案并非理想。
例如,目前,我在settings.py中执行类似的操作(对于每个小部件的媒体):
# settings.py
...
from my_app1.widgets import Widget1
from my_app1.widgets import Widget2
from my_app1.widgets import Widget3
...
widgets = {
'my_widget1': Widget1(),
'my_widget2': Widget2(),
'my_widget3': Widget3(),
...
}
for name, widget in widgets.items():
COMPRESS_OFFLINE_CONTEXT['{}_css'.format(name)] = widget.media['css']
COMPRESS_OFFLINE_CONTEXT['{}_js'.format(name)] = widget.media['js']
然后在模板中,我这样做:
{% compress js %}
{{ my_widget1_js }}
{% endcompress %}
有没有办法以更接近Django {{ form.media }}
方法的方式处理这种情况,或者可能无需枚举特定媒体到每个窗口小部件或每个窗体(包含媒体)网站?
答案 0 :(得分:0)
您可以使用__getattr__
方法使用某个自定义类来简化设置。这样,如果您将该对象传递给模板并尝试调用
{{ obj.my_widget1_js }}
__getattr__
内的逻辑可以搜索项目中的指定小部件并返回它的媒体。
将自动发现每个小部件的类示例:
class WidgetImporter(object):
def __getattr__(self, name):
path = name.split('__') # this will split path on double underscore, so you can define submodule here
path = [(node, "".join(part.capitalize() for part in node.split('_'))) for node in path] # this will convert underscore_names to CamelCase names.
# determining for each module if it's name is CamelCased or underscored
real_path = []
for underscored, cameled in path:
try:
__import__(".".join(real_path + [underscored])) # first trying to import umderscored module
except ImportError:
try:
__import__(".".join(real_path + [cameled])) # now try with cameled
except ImportError:
return "" # or raise some exception here if you like
else:
real_path.append(cameled)
else:
real_path.append(underscored)
last_node = real_path[len(real_path) - 1]
return getattr(__import__(".".join(real_path), fromlist=[last_node]), last_node)() # returning actual class instance
这样你可以在settings.py文件中使用它:
COMPRESS_OFFLINE_CONTEXT = {
'widgets': WidgetImporter(),
}
并在您的模板中使用:
{{ widgets.my_app1__widgets__widget1.media.css }}
类将尝试将my_app1__widgets__widget1
解析为您的类的实际路径,并尝试导入它。如果成功,将打印media['css']
。它不是100%最佳代码和100%安全(如果有人可以访问您的模板,可能会有一些漏洞),但它会完成这项工作。