4

I have several models in my application, and as I will have some views doing the same thing (form + tables showing existing records in my model), but implemented dfferently because of the model, which will be different in each case, I was wondering if it was possible to make it generic.

I googled a bit and was not able to find anything relevant to my case. What I would like to achieve:

In my view, I want to go through each object from the model that I passed to the template, for example:

return render_template('addstatus.html', form=form, statuses=Status.query.all(), 
        target_model="Status", fields=Status.__mapper__.c.keys())

But I want to have only one view, whatever the model will be, so I am not able to know in advance the fields of my model, the number of columns and so on.

I want to have something like that in my view:

{% for obj in objects %}
   {% for field in obj.fields %} (not existing)
      <h1> {{ field }} :: {{ obj.fields.field.value }}
   {% endfor %}
{% endfor %}

Is it something possible? How can I achieve that?

Jeremy D
  • 4,787
  • 1
  • 31
  • 38
  • It appears you want to iterate over all of the defined columns in your model, then use the results to automatically create the form. It looks like you are on your way to what the template needs, but are looking for how to iterate over the columns. I suggest you look at [these](http://stackoverflow.com/questions/2537471/method-of-iterating-over-sqlalchemy-models-defined-columns) [questions](http://stackoverflow.com/questions/2441796/how-to-discover-table-properties-from-sqlalchemy-mapped-object) which will give you ideas on how to do that. Then you just need to join the ideas together. – Mark Hildreth Oct 06 '13 at 22:01
  • I actually don't want to create a form. I want to create a but without knowing in advance my model fields and object model values in my for loop.
    – Jeremy D Oct 07 '13 at 20:33
  • I'm sorry, I should have said "the HTML" instead of "the form". However, the same idea applies: the only missing link for what you need is to determine how to loop over the fields in a declarative SQLAlchemy model. Those other questions show you how you might be able to do that. – Mark Hildreth Oct 07 '13 at 20:35
  • Oh OK, sorry for not investigating before asking again. – Jeremy D Oct 07 '13 at 20:38

2 Answers2

4

You can add this method to your db.Model class (either by subclassing or by monkeypatching):

from sqlalchemy.orm import class_mapper, ColumnProperty
def columns(self):
    """Return the actual columns of a SQLAlchemy-mapped object"""
    return [prop.key for prop in class_mapper(self.__class__).iterate_properties
            if isinstance(prop, ColumnProperty)]

Then you can use {% for col in obj.columns() %} to iterate over the column names.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
0

I had a similar issue, and wanted something purely Jinja2 based. This will return all of the keys/fields in your "obj" table, and worked well for me:

obj.__table__.columns._data.keys()

Here it is implemented in your sample code

{% for obj in objects %}
    {% for field in obj.__table__.columns._data.keys() %}
        <h1> {{ field }} :: {{ obj[field] }} </h1>
    {% endfor %}
{% endfor %}
Mark Hebert
  • 919
  • 1
  • 9
  • 15