Как использовать тег addtoblock от sekizai внутри шаблона виджета формы

#django #django-widget #django-context #django-sekizai

#django #django-виджет #django-контекст #django-sekizai

Вопрос:

Я пишу пользовательское поле формы, в котором есть пользовательский виджет. Виджету нужны некоторые статические ресурсы. Его шаблон выглядит следующим образом:

 {% 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 — на самом деле НЕ решает проблему. В конце концов, недостатки медиа-класса — вот почему 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 link в head и тег js script после body).

Если у кого-нибудь есть решение для использования addtoblock от sekizai в шаблоне, который не имеет доступа к объекту запроса, все равно добро пожаловать!

Обновление 2

Я могу использовать addtoblock и избежать ошибки контекста, переопределяющей метод 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
  

Однако ресурсы по-прежнему не отображаются…

Ответ №1:

Немного подумав и прочитав документы, я понимаю, что статические ресурсы для форм и виджетов выполняются django «из коробки»:

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