Fix readonly default renderers for association proxy fields

This commit is contained in:
Lance Edgar 2018-01-10 21:18:38 -06:00
parent bfa398bee1
commit e3ca3c9370

View file

@ -67,6 +67,31 @@ def get_association_proxy(mapper, field):
return desc 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): class CustomSchemaNode(SQLAlchemySchemaNode):
def association_proxy(self, field): def association_proxy(self, field):
@ -344,21 +369,31 @@ class Form(object):
if not self.model_class: if not self.model_class:
raise ValueError("Must define model_class to use make_renderers()") raise ValueError("Must define model_class to use make_renderers()")
mapper = orm.class_mapper(self.model_class) inspector = sa.inspect(self.model_class)
renderers = {} renderers = {}
for field in self.fields: # TODO: clearly this should be leaner...
if mapper.has_property(field):
prop = mapper.get_property(field) # first look at regular column fields
for prop in inspector.iterate_properties:
if isinstance(prop, orm.ColumnProperty): if isinstance(prop, orm.ColumnProperty):
if len(prop.columns) == 1: if len(prop.columns) == 1:
column = prop.columns[0] column = prop.columns[0]
if isinstance(column.type, sa.DateTime): if isinstance(column.type, sa.DateTime):
renderers[field] = self.render_datetime renderers[prop.key] = self.render_datetime
elif isinstance(column.type, sa.Boolean): elif isinstance(column.type, sa.Boolean):
renderers[field] = self.render_boolean renderers[prop.key] = 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 return renderers