If you have a table with fifty or more fields, you may get tired of repeating them again and again. This shortcut saves typing and also minimizes mismatch errors.
Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import pprint from myapp.model import MyORMClass class MyController(BaseController): def _update_my_attributes(self, my_object): data = self.form_result log.debug("form input = %s", pprint.pformat(data)) my_object.field1 = data["field1"] ... # Or if you prefer to use a loop. fieldnames = [x.name for x in MyORMClass.c] for fieldname in fieldnames: value = data[fieldname] setattr(my_object, fieldname, value) @validate(schema=SomeSchema(), form="new") def create(self): my_object = MyORMClass() self._update_my_attributes(my_object) meta.Session.save(my_object) meta.Session.flush() # Write the object so it has a primary key. assert my_object.id, "Failed to add MyORMClass to database." meta.Session.commit() redirect_to(... display page ...) @validate(schema=SomeSchema(), form="edit") def update(self): my_object = MyORMClass.get(PRIMARY_KEY_THAT_I_KNOW_SOMEHOW) self._update_my_attributes(my_object) meta.Session.commit() redirect_to(... display page ...) |
Generic function
If you want to make this even more generic, you can replace ._update_my_attributes with a function:
1 2 3 4 5 6 7 8 9 10 | def update_orm_instance(instance, data): """Update a new or existing ORM instance from user input. ``instance`` is a SQLAlchemy ORM instance (mapped class). ``data`` is a dict of user input whose keys correspond to ``instance`` attributes. """ fieldnames = [x.name for x in instance.__class__.c] for fieldname in fieldnames: value = data[fieldname] setattr(my_object, fieldname, value) |
Commentary
Fieldname loops may look convenient but they're kind of magical, and they don't provide any way to customize certain fields; e.g., to convert the value to another type, skip certain fields, set values in related tables, etc. Still, if your needs are straightforward, this might be a pattern for you.