Quoting "Bud P. Bruegger" <bu...@si...>:
> Important is probably that there are no explicit database methods such
> as insert (store, save) and update. This is done implicitly while
> using the object (i.e., attribute access).
Yep, and this is the main selling point for SQLObject for me. A class acts (in
use - i know you disagree about defining classes) just like a python object.
> When SQLObject retrieves an object from the db, it first gets a list
> of column values and then calls the objects class (eg., p=Person()) to
> create an object instance and then sets all the values. [I derive
> this from the statement from the manual that "__init__ is called
> everytime an object is just fetched from the cache"].
>
> What in plain python classes normally goes in __init__ should go in
> the _init method for SQLObject subclasses. _init seems to be called
> by SQLObject's new method.
A little misunderstanding here. Off the top of my head this problem will occur
for any system that may transparently return an internally cached object on
'creation'. You're free to do whatever you please in an SQLObject __init__
method, so long as you realize it will be called whether this is a new object
(Person.new()), an exisiting row (Person(12)), or an existing object
(Person(12) that returns a cached value). It seems to me that 'typical' python
__init__ stuff is only relevant to the first case, and that any ORM system
should provide ways to override the first two separately (for SO, .new and
._init), and probably probably hide the third case from users. But we can
probably agree that this behavior is not 'normal' python behavior, that it
would be nice if __init__ could be used for the first case... but what do you
do for the second case?
Note that the call cycle in python (SQLObject) is:
for Person.new():
new
__new__ (explicit in new)
__init__ (implicit after __new__)
set (explicit in new)
_init (explicit in new/finishCreate)
for Person(12) (not cached):
__new__
_init (explicit in __new__)
__init__ (implicit after __new__)
for Person(12) (cached):
__new__
__init__ (implicit after __new__)
> 2. Possible Alternative Approach
> --------------------------------
>
> A possible alternative approach makes a major change in the look and
> feel inassuch that persistence methods (insert, update, ..) need to be
> called explicitly.
>
> * same goes for resolution of collisions in concurrancy control. I
> don't see a way of hiding these issues from the application
> programmer
Agreed. I suppose this directly relates to my problem with any foreignKey
access possibly causing an SQLObjectNoFound error; with constraints and
collisions, any attribute access could conceivably need to be safe-guarded.
Not sure how I feel about that. While I initially don't like explicit storage
commands, I'm also not excited about how to deal with the above.
> So in this case, column values could be stored in normal attributes
> (in the __dict__) without the need for properties that overload the
> setter method to update the db.
>
> To retrieve an object from the db, a first step retrieves the column
> values, then creates an empty object using <class>.__new__(<class>)
> (thus avoiding __init__) and then assign the (unmarshelled) values to
> the __dict__ (or better through use of normal setattr).
See above, it's impossible in python to call __new__ and avoid __init__ to my
knowledge.
> * I believe (haven't verified) that it should be possible for users
> to define properties in lieu of just normal __dict__ items without
> any adverse effects. (I reason that the use of getattr and
> setattr by the middleware works equally well)
Just to be clear, there's no danger in setting your own properties in
SQLObject. SQLObject tries to help by letting you just define _get/_set and
get a property generated, but manually created properties will just be
ignored.
I think the key thing to think about here is how collisions or constraints
affect using SQLObject at the attribute level.
- Luke
|