Ronald Jaramillo wrote:
> Rather than complete form generation I will like to work with some kind
> of 'smart' view. This could be bundles of controller code, Kid
> templates and Mochi stuff, that understand how to render certain objects.
> This bundles could be distributed as an egg so people could drop them
> into their app.
> A view could implement some kind of default presentation based on the
> standard SQLObject types and let your app register as delegate for
> certain aspects of the presentation and user interaction.
> Personally I will love to se a powerful grid view that knew how to
> render different kinds of tabular data and wasn't ashamed to ask when
> it didn't ; )
This is an ideal place for generic functions. E.g.:
@dispatch.generic()
def html(obj, context):
# Use XML() to return HTML, not just a string
return repr(obj)
@html.when('isinstance(obj, SQLObject)')
def sql_html(obj, context):
rows = []
for column in obj.sqlmeta.columnList:
value = getattr(obj,
column.name)
restore = context.push_attr(sqlobject=obj, column=column,
column_name=
column.name,
short=True)
try:
rows.append('<tr><td>%s</td><td>%s</td></tr>' % (desc,
value))
finally:
restore.pop_attr()
return XML('<table>%s</table>' % '\n'.join(rows))
and so forth. This is a really easy way to implement both general rules
(e.g., use repr()), and specific rules. And you can do really specific
overrides:
@html.when('isinstance(obj, Article) and context.short')
def short_html(obj, context):
return obj.title
# Show the beginning of long texts...
@html.when('context.short and isinstance(obj, (str, unicode)) and
len(obj) > 40')
def short_text(obj, context):
return obj[:40]+'...'
# but show the beginning and end of article bodies
@html.when('isinstance(context.sqlobject, Article) and
context.column_name="body" and context.short')
def short_article_body(obj, context):
return obj[:20]+'...'+obj[20:]
And hopefully from this it should be clear how someone using other kinds
of objects (that aren't SQLObject objects) could
> For example when displaying an object in CatWalk, if the object has a
> ForeignKey, it will show the referred object's id. If the referred
> object was, let's say, a 'Book' object, the obvious label to display
> will be the book title. But in another context the best label to
> display in a view could be the ISBN number.
> That's why I think that the "adding 'metadata' to my models" approach
> can only take you that far. I will rather see a system where the view
> will let you implement a delegate like
> 'columnToUseAsLabelForForeignKey' where you could return 'title',
> 'ISBN' or another column name based on the context.
I think generic functions can handle this much more cleanly than a
collection of attributes like columnToUseAsLabelForForeignKey. The key
being the magical context argument (which is like
formencode.fields.Context, but what I describe here doesn't match it
exactly); that allows you to make specific overrides based on the
context of where you are rendering an object. The way generic functions
choose an implementation is also a very good match for this, I think.
--
Ian Bicking /
ia...@colorstudy.com /
http://blog.ianbicking.org