0

我正在编写一个具有自定义小部件的自定义表单字段。小部件需要一些静态资产。它的模板如下所示:

{% load sekizai_tags static %}
<div id="myWidget"> ... </div>

{% addtoblock "css" %}
<link rel="stylesheet" href="{% static 'my_app/css/widget.css' %}">{% endaddtoblock %}
{% addtoblock "js" %}
<script src="{% static 'my_app/js/widget.js' %}"></script>{% endaddtoblock %}

但是,这不起作用。我得到:You must enable the 'sekizai.context_processors.sekizai' template context processor or use 'sekizai.context.SekizaiContext' to render your templates.

我猜这是因为表单(和小部件)无法访问请求对象?!有没有解决的办法?

我在 sekizai中发现提到 SekizaiContext 为...

在没有可用请求的地方使用替代上下文而不是 RequestContext。

...但我无法弄清楚我会如何做到这一点。

请注意,我不想开始传递请求。这不是一个可接受的解决方案,因为我的自定义字段是可重用的;它应该以任何形式工作而无需进一步修改。

更新

实际上,在发布了我自己的问题的答案并且......再想一想之后,我意识到这个答案 - 使用 Media 类 - 并没有真正解决这个问题。毕竟,Media 类的缺点是首先需要 sekizai 的原因。

使用 Media 类意味着:

# widgets.py

class MyWidget(widgets.Widget):
    template_name = "my_widget.html"
    # other stuff

    class Media:
            css = {"all": "my_app/css/widget.css"}
            js = ("my_app/js/widget.js")

然后,添加{{ form.media }}到包含表单的模板。因此,发布此问题的初衷不会得到解决。即在小部件模板中使用addtoblock,以便可以按原样使用该字段,而无需对其他模板进行进一步修改。

此外,如果{{ form.media }}使用了 html 标签,它将在表单之后立即呈现,除非我像这样包装它:{% addtoblock "css" %}{{ form.media }}{% endaddtoblock %}. 然后将 css 和 js 都添加到同一个位置(而通常需要在头部添加 css 链接标签,在正文后添加 js 脚本标签)。

如果有人有在无法访问请求对象的模板中使用 sekizai 的 addtoblock 的解决方案,仍然欢迎!

更新 2

我能够使用 addtoblock 并避免覆盖我的 widgets.Widget 子类中的 get_context 方法的上下文错误,如下所示:

# widget.py
class MyWidget(widgets.Widget):

def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        sezikai_ctx_var = get_varname()
        sekizai_ctx = SekizaiContext().flatten()
        context.update({sezikai_ctx_var: sekizai_ctx[sezikai_ctx_var]})
        return context

但是,资产仍然没有渲染......

4

1 回答 1

0

经过一番思考和阅读文档,我意识到表单和小部件的静态资产是由 django 开箱即用的:

https://docs.djangoproject.com/en/3.1/topics/forms/media/

于 2020-10-04T21:52:07.993 回答