diff --git a/tailbone/forms2/core.py b/tailbone/forms2/core.py index a23470c7..f3a3cae7 100644 --- a/tailbone/forms2/core.py +++ b/tailbone/forms2/core.py @@ -67,6 +67,31 @@ def get_association_proxy(mapper, field): return desc +def get_association_proxy_target(inspector, field): + """ + Returns the property on the main class, which represents the "target" + for the given association proxy field name. Typically this will refer + to the "extension" model class. + """ + proxy = get_association_proxy(inspector, field) + if proxy: + proxy_target = inspector.get_property(proxy.target_collection) + if isinstance(proxy_target, orm.RelationshipProperty) and not proxy_target.uselist: + return proxy_target + + +def get_association_proxy_column(inspector, field): + """ + Returns the property on the proxy target class, for the column which is + reflected by the proxy. + """ + proxy_target = get_association_proxy_target(inspector, field) + if proxy_target: + prop = proxy_target.mapper.get_property(field) + if isinstance(prop, orm.ColumnProperty) and isinstance(prop.columns[0], sa.Column): + return prop + + class CustomSchemaNode(SQLAlchemySchemaNode): def association_proxy(self, field): @@ -344,21 +369,31 @@ class Form(object): if not self.model_class: raise ValueError("Must define model_class to use make_renderers()") - mapper = orm.class_mapper(self.model_class) + inspector = sa.inspect(self.model_class) renderers = {} - for field in self.fields: - if mapper.has_property(field): - prop = mapper.get_property(field) - if isinstance(prop, orm.ColumnProperty): - if len(prop.columns) == 1: - column = prop.columns[0] + # TODO: clearly this should be leaner... - if isinstance(column.type, sa.DateTime): - renderers[field] = self.render_datetime + # first look at regular column fields + for prop in inspector.iterate_properties: + if isinstance(prop, orm.ColumnProperty): + if len(prop.columns) == 1: + column = prop.columns[0] + if isinstance(column.type, sa.DateTime): + renderers[prop.key] = self.render_datetime + elif isinstance(column.type, sa.Boolean): + renderers[prop.key] = self.render_boolean - elif isinstance(column.type, sa.Boolean): - renderers[field] = self.render_boolean + # then look at association proxy fields + for key, desc in inspector.all_orm_descriptors.items(): + if desc.extension_type == ASSOCIATION_PROXY: + prop = get_association_proxy_column(inspector, key) + if prop: + column = prop.columns[0] + if isinstance(column.type, sa.DateTime): + renderers[key] = self.render_datetime + elif isinstance(column.type, sa.Boolean): + renderers[key] = self.render_boolean return renderers