[Django]-Pass field value to custom layout.Field

3👍

There is field context variable passed to that template which contains the FormField object. So you should be able to do this:

<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>

The reason you have to do field.field is that the field that is passed to the template is a BoundField object, rather than the IntegerField that you defined in your form class. That object is stored in BoundField.field – hence field.field.

The BoundField has a value() method which is why field.value works.

2👍

I am going to put here my current progress, even though this is not yet solved (but I am getting closer I hope). I have tried the following to solve this:

  • used django-debug-toolbar: great, but the context dump is not readable for complex templates. It is just a huge __repr__ dump, not browsable at all, and lacking information (since the __repr__s by necessity are shortened)

  • used {% debug %} in the template: even worse. I can not read that. It helps maybe for small templates, but if you have a form with 5 fields, and three other template tags, good luck with reading that.

  • used a pdb breakpoint to access the context. pdb gives you an interactive interface to the context, but it is not easy to use.

  • used an ipdb breakpoint. This is a little better, but it is not possible to use magic functions (even though are listed).
  • used an embedded ipython shell. This is a game changer. Suddenly you are possible to easily browse context, related functions, code, automatically pretty print everything, use tab completion, …

My templatetags for this have been (file 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()

And you can use it in the template like:

{% 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>

(You need to pip install ipython and ipdb)

This is an example session:

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']

And thanks to the ipython shell, I was able to find that the max value is in {{field.field.max_value}}. No idea why a double field specifier is needed, but it works.

Leave a comment