[TurboGears] ウィジェットに渡したvalue変数は、テンプレート内では辞書になる。

環境

この記事の内容は、TurboGears 1.0.1で確認しました。

現象

turbogears.widgets.forms.CompoundInputWidgetクラスを継承しているクラス(Formクラスなど)のdisplayメソッドのvalue引数に属性を持つオブジェクトを渡すとします。例えば、

class Foo:
    pass

foo = Foo()
foo.bar = "baz"

のように生成したオブジェクトと、

class Hoge(Form):
    template = """
(略)
"""

hoge = Hoge()

というフォームウィジェットがあり、これらをテンプレート内で、

${hoge.display(value=foo)}

として使用します。すると、Hogeクラスのテンプレート内では、変数valueは辞書となっており、barという属性を読み出すためには、

${value['bar']}

としなければなりません。

詳細

turbogears.widgets.base.Widgetクラスでは、displayメソッドは以下のようになっています。

class Widget(object):
(略)
    def display(self, value=None, **params):
(略)
        params["value"] = to_unicode(self.adjust_value(value, **params))
(略)

この中のadjust_valueメソッドは、turbogears.widgets.forms.CompoundInputWidgetで以下のようにdictify_valueメソッドを呼び出しています。このdictify_valueメソッドを使って、変数valueの型を辞書に変換しています。

class CompoundInputWidget(CompoundWidget, InputWidget):
(略)
    def dictify_value(self, value):
        """Converts a value into a dict suitable for propagating values to
        child widgets. If value is a dict it will pass thorugh, if it other
        kind of object, attributes which match child widgets' names will be 
        tried to fetch."""
        if isinstance(value, dict):
            return value
        else:
            value_as_dict = {}
            for w in self.iter_member_widgets():
                try:
                    value_as_dict[w.name] = getattr(value, w.name)
                except AttributeError:
                    pass
            return value_as_dict

    def adjust_value(self, value=None, **params):
        """Adjust a value for displaying in a widget."""
        if value is not None:
            value = self.dictify_value(value)
        return super(CompoundWidget, self).adjust_value(value, **params)