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

时间:2015-11-05 00:12:08

标签: django django-crispy-forms

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

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时,如何将值传递给模板?如何从相关的Formfield获取最小/最大值?

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

如果我理解正确,custom-slider.html是一个功能齐全的django模板。背景是什么?它是否可以访问相关的表单字段?怎么样?我无法找到一个例子。

2 个答案:

答案 0 :(得分:2)

传递给该模板的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对象,而不是您在自己定义的IntegerField形式类。 对象is stored in BoundField.field - 因此field.field

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

答案 1 :(得分:2)

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

  • 使用django-debug-toolbar:很好,但上下文转储对于复杂模板是不可读的。它只是一个巨大的__repr__转储,根本不可浏览,而且缺少信息(因为__repr__ s必然会缩短)

  • 在模板中使用了{% 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}}。不知道为什么需要双字段说明符,但它可以工作。