将字段值传递给自定义 layout.Field

Pass field value to custom layout.Field

我正在定义自定义布局对象:

Field('slider', template="custom-slider.html")

documentation 所示:

我的自定义滑块是:

<div class="slider slider-green" data-prefix="&euro; " data-postfix=",-" data-min="0" data-max="1800" data-value="223"></div>

但我想参数化这些值。我怎样才能做到这一点?使用 layout.Field 时如何将值传递给模板?如何从相关的表单域中获取 min/max 值?

slider = forms.IntegerField(label="slider", min_value=3, max_value=50)

如果我理解正确,custom-slider.html 是一个功能齐全的 django 模板。上下文是什么?它是否有权访问相关的表单字段?如何?我找不到示例。

field 上下文变量传递给包含 FormField 对象的模板。所以你应该能够做到这一点:

<div class="slider slider-green" data-prefix="&euro; " data-postfix=",-"
data-min="{{ field.field.min_value }}" data-max="{{ field.field.max_value }}"
data-value="{{ field.value }}"></div>

您必须执行 field.field 的原因是传递给模板的 fieldBoundField object, rather than the IntegerField that you defined in your form class. That object is stored in BoundField.field - 因此 field.field.

BoundField 有一个 value() 方法,这就是 field.value 起作用的原因。

我将把我目前的进展放在这里,尽管这还没有解决(但我希望我越来越接近)。我尝试了以下方法来解决这个问题:

  • 已使用 django-debug-toolbar:很好,但是复杂模板的上下文转储不可读。这只是一个巨大的 __repr__ 转储,根本无法浏览,并且缺少信息(因为 __repr__ 必须缩短)

  • 在模板中使用了 {% debug %}:更糟。我看不懂。它可能对小型模板有帮助,但如果您有一个包含 5 个字段和三个其他模板标签的表单,祝您阅读顺利。

  • used a pdb breakpoint 访问上下文。 pdb 为您提供上下文的交互界面,但使用起来并不容易。

  • 使用了 ipdb 断点。这样好一点,但不是possible to use magic functions(虽然都列出来了)。
  • 使用了 embedded ipython shell。这是一个游戏规则改变者。突然之间,您可以轻松浏览上下文、相关函数、代码,自动漂亮地打印所有内容,使用制表符完成,...

我的 templatetags 是(文件 templatetags/debug.py):

from django.template import Library, Node


register = Library()


class PdbNode(Node):

    def render(self, context):
        import pdb as pdb_module
        pdb_module.set_trace()
        return ''


class IPdbNode(Node):

    def render(self, context):
        import ipdb as ipdb_module
        ipdb_module.set_trace()
        return ''


class EmbedIPythonNode(Node):

    def render(self, context):
        from IPython import embed
        embed()
        return ''


@register.tag
def pdb(parser, token):
    return PdbNode()


@register.tag
def ipdb(parser, token):
    return IPdbNode()


@register.tag
def ipython(parser, token):
    return EmbedIPythonNode()

您可以在模板中使用它,例如:

{% load debug %}
{% ipython %}
{% pdb %}
{% ipdb %}

<row>
  <div class="col-lg-6""></div>
  <div class="col-lg-6"">
    <div class="slider {{field.extra_class}}" data-prefix="{{field.prefix}}" data-postfix="{{field.postfix}}" data-min="{{widget.min}}" data-max="{{widget.max}}" data-value="{{field.value}}"></div>
  </div>
</row>

(你需要 pip install ipythonipdb

这是一个示例会话:

In [15]: dir(context.dicts[5]['field'])
Out[15]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__getitem__',
 '__hash__',
 '__html__',
 '__init__',
 '__iter__',
 '__len__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__unicode__',
 '__weakref__',
 '_initial_value',
 'as_hidden',
 'as_text',
 'as_textarea',
 'as_widget',
 'auto_id',
 'css_classes',
 'data',
 'errors',
 'field',
 'form',
 'help_text',
 'html_initial_id',
 'html_initial_name',
 'html_name',
 'id_for_label',
 'is_hidden',
 'label',
 'label_tag',
 'name',
 'value']

感谢 ipython shell,我能够发现最大值在 {{field.field.max_value}} 中。不知道为什么需要双字段说明符,但它有效。