将字段值传递到自定义布局。

3

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

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

如文档所示:My custom-slider 是:

我的自定义滑块是:

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

但我希望将这些值参数化。我该怎么做?在使用布局字段时,如何传递值到模板?如何从相关表单字段中获取最小/最大值?

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

如果我理解正确,custom-slider.html 是一个完全功能的 Django 模板。那么它的上下文是什么?它可以访问相关的表单字段吗?如何访问?我找不到一个例子。

2个回答

3

在该模板中传递了一个名为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 的原因是,在模板中传递的 field 是一个 BoundField 对象,而不是你在表单类中定义的 IntegerField。那个对象存储在 BoundField.field - 因此需要使用 field.fieldBoundField 有一个 value() 方法,这就是为什么 field.value 起作用的原因。

谢谢,但对我没有用。这些值在我的模板中是空的,除了{{field.value}},它有正确的值。我如何访问上下文以查看可用的值/对象?我想查看上下文中的field对象。你有什么技巧吗?我已经安装了django-debug-toolbar,但我无法在那里看到上下文中的field对象。在渲染特定模板时是否可以进入iPython shell(一种模板断点)? - blueFast
在你的模板顶部加入{% debug %} - 这将为您提供要检查的上下文。 - solarissmoke
我已经完成了这个,并且还使用了django-debug-toolbar,浏览了crispy-form实现,并使用了templatetag在模板中启动调试器(包括pdb和ipdb),并浏览了django.template.context.RequestContext的实现,但是我无法找到如何列出字段上下文对象的所有可用属性。max_valuemin_value绝对不可用,但value是可用的。你怎么知道哪些对象/属性应该在模板中可用? - blueFast
如果你能找到 field 对象,那么检查 type(field) 确保它是你所期望的 IntegerField,并使用 dir(field) 查看它公开了哪些属性和方法。这会给你什么信息? - solarissmoke
1
我已经添加了我的调试过程的详细答案,这可能对其他人有所帮助。不要问我为什么,但最大/最小值在 {{field.field.max_value}} 中(也就是一个 double 字段说明符)。而该值在 {{field.value}} 中,正如你正确地指出的那样。就因为这个,我给你点赞,但请纠正其他说明符以避免混淆。 - blueFast
我找到了为什么会这样的原因...我会在我的回答中发布一个解释。 - solarissmoke

2
我打算在这里记录下我当前的进展,虽然这还没有解决(但我希望我正在接近)。我尝试了以下方法来解决这个问题:
  • 使用了django-debug-toolbar:很好,但是对于复杂模板的上下文转储不可读。它只是一个巨大的__repr__转储,完全无法浏览,并且缺少信息(因为__repr__必须被缩短)

  • 在模板中使用{% debug %}:更糟糕。我无法阅读它。它可能有助于小型模板,但如果您有一个包含5个字段和三个其他模板标记的表单,那么祝你好运。

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

  • 使用了ipdb断点。这稍微好一些,但不能使用魔术函数(即使已列出)。
  • 使用了嵌入式IPython shell。这是一个改变游戏规则的技巧。突然间,您可以轻松浏览上下文、相关函数、代码,自动漂亮地打印所有内容,使用制表符完成等等。
我的模板标签是通过文件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>

您需要安装ipythonipdb,可以使用pip install命令进行安装。
以下是一个示例会话:
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}}。不知道为什么需要双重字段说明符,但它可以工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接