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.