Thread: [SQLObject] a couple of questions: field inheritance and update/instert distinction
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Diez B. R. <die...@ar...> - 2006-11-27 16:38:33
|
Hi all, I'm having two simple questions here: 1) I'd like to have a kind of multiple inheritance like it is available wit= h=20 mixins. What I mean by this is something along these lines: class Auditable(...): created =3D DateTimeCol(notNone=3DTrue) class SomeThing(SQLObject, Auditable): foo =3D StringCol() And I now would like to see created being a column of SomeThing I could of course go with a InheritableSQLObject for this simple case - but= =20 first of all I don't want to have all the joins that produces, and second=20 there might be cases where I could need another aspect, like e.g. Deletable= =20 that marks objects as deleted (without actually deleting them) Is there anything like this possible - apart from re-iterating all the colu= mns=20 in each class? 2) The docs about _init are unclear to me, and somehow I didn't make things= =20 work properly. What I'm after is a way to have a co-object that shares the= =20 life-cycle of my original object. In my case, it is a special User that ha= s=20 a special Item associated with it. Now I can overload destroySelf to get rid of the co-item in case of delete= ,=20 but I didn't manage to distinguish update/insert in case of object creation= -=20 so that in the latter case, I'd be able to create the co-object. I helped=20 myself with a classmethod, but for the sake of beauty I'd actually prefer a= =20 constructor-based approach if possible. Any hints welcome. =2D-=20 >> Diez B. Roggisch >> Developer T +49 (30) 443 50 99 - 27 =46 +49 (30) 443 50 99 - 99 M +49 (179) 11 75 303 E die...@ar... >> artnology GmbH A Milastra=C3=9Fe 4 / D-10437 Berlin T +49 (30) 443 50 99 - 0 =46 +49 (30) 443 50 99 - 99 E in...@ar... I http://www.artnology.com |
From: Oleg B. <ph...@ph...> - 2006-11-27 17:35:43
|
On Mon, Nov 27, 2006 at 05:38:09PM +0100, Diez B. Roggisch wrote: > 1) I'd like to have a kind of multiple inheritance like it is available with > mixins. What I mean by this is something along these lines: > > class Auditable(...): > created = DateTimeCol(notNone=True) > > class SomeThing(SQLObject, Auditable): > foo = StringCol() > > > And I now would like to see created being a column of SomeThing This should work as expected: class Auditable(SQLObject): created = DateTimeCol(notNone=True) class Deletable(SQLObject): deleted = DateTimeCol(notNone=True) class SomeThing(Auditable, Deletable): foo = StringCol() What InheritableSQLObject does: it stores "created" and "deleted" in their own tables (classes). Simple SQLObject stores these attributes in SomeThing. No, InheritableSQLObject does not support multiple inheritance, and probably never will. > 2) The docs about _init are unclear to me, and somehow I didn't make things > work properly. What I'm after is a way to have a co-object that shares the > life-cycle of my original object. In my case, it is a special User that has > a special Item associated with it. I do not understand the question. Can you say this in a (pseudo-)code? Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Diez B. R. <die...@ar...> - 2006-11-27 18:04:41
|
> This should work as expected: > > class Auditable(SQLObject): > created =3D DateTimeCol(notNone=3DTrue) > > class Deletable(SQLObject): > deleted =3D DateTimeCol(notNone=3DTrue) > > class SomeThing(Auditable, Deletable): > foo =3D StringCol() Will give it a shot, thanks. > What InheritableSQLObject does: it stores "created" and "deleted" in > their own tables (classes). Simple SQLObject stores these attributes in > SomeThing. > No, InheritableSQLObject does not support multiple inheritance, and > probably never will. I'm fine with that. > > 2) The docs about _init are unclear to me, and somehow I didn't make > > things work properly. What I'm after is a way to have a co-object that > > shares the life-cycle of my original object. In my case, it is a speci= al > > User that has a special Item associated with it. > > I do not understand the question. Can you say this in a (pseudo-)code? Basically, I want this: class User(SQLObjec): ... def _init(self, *args, **kwargs): if <the_table_row_is_created>: co_object =3D CoObject(userID=3Dself.id) return super(User, self)._init(*args, **kwargs) This will ensure there is a CoObject whenever there is a User. Did this clear things up for you? =2D-=20 >> Diez B. Roggisch >> Developer T +49 (30) 443 50 99 - 27 =46 +49 (30) 443 50 99 - 99 M +49 (179) 11 75 303 E die...@ar... >> artnology GmbH A Milastra=DFe 4 / D-10437 Berlin T +49 (30) 443 50 99 - 0 =46 +49 (30) 443 50 99 - 99 E in...@ar... I http://www.artnology.com |
From: Oleg B. <ph...@ph...> - 2006-11-27 18:47:55
|
On Mon, Nov 27, 2006 at 07:04:33PM +0100, Diez B. Roggisch wrote: > class User(SQLObjec): > ... > > def _init(self, *args, **kwargs): > if <the_table_row_is_created>: > co_object = CoObject(userID=self.id) > return super(User, self)._init(*args, **kwargs) > > This will ensure there is a CoObject whenever there is a User. _init() is called during creation, so you can be sure the row has not been inserted into the DB yet, and there is no is. You need to change the order of operations: def _init(self, *args, **kwargs): super(User, self)._init(*args, **kwargs) # Perform INSERT and get the id co_object = CoObject(userID=self.id) _init() really is the best method to override for INSERT, but there is no single method to override for UPDATEs... Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Diez B. R. <die...@ar...> - 2006-11-27 19:03:27
|
On Monday 27 November 2006 19:47, Oleg Broytmann wrote: > On Mon, Nov 27, 2006 at 07:04:33PM +0100, Diez B. Roggisch wrote: > > class User(SQLObjec): > > ... > > > > def _init(self, *args, **kwargs): > > if <the_table_row_is_created>: > > co_object =3D CoObject(userID=3Dself.id) > > return super(User, self)._init(*args, **kwargs) > > > > This will ensure there is a CoObject whenever there is a User. > > _init() is called during creation, so you can be sure the row has not > been inserted into the DB yet, and there is no is. You need to change the > order of operations: Maybe that then was the trouble for me, thank you! > def _init(self, *args, **kwargs): > super(User, self)._init(*args, **kwargs) # Perform INSERT and > get the id co_object =3D CoObject(userID=3Dself.id) > > _init() really is the best method to override for INSERT, but there is > no single method to override for UPDATEs... =46ine for me, I can do whatever is needed there using properties anyway. Thanks for your quick help, =2D-=20 >> Diez B. Roggisch >> Developer T +49 (30) 443 50 99 - 27 =46 +49 (30) 443 50 99 - 99 M +49 (179) 11 75 303 E die...@ar... >> artnology GmbH A Milastra=DFe 4 / D-10437 Berlin T +49 (30) 443 50 99 - 0 =46 +49 (30) 443 50 99 - 99 E in...@ar... I http://www.artnology.com |
From: Oleg B. <ph...@ph...> - 2006-11-27 19:09:51
|
On Mon, Nov 27, 2006 at 08:03:02PM +0100, Diez B. Roggisch wrote: > > _init() really is the best method to override for INSERT, but there is > > no single method to override for UPDATEs... > > Fine for me, I can do whatever is needed there using properties anyway. There is method set() that is being called during both INSERT (it is called in _create() before _init()) and UPDATE. There are also methods _SO_getValue and _SO_setValue - low-level methods that are used to construct getters and setters for properties... Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Diez B. R. <die...@ar...> - 2006-11-28 17:41:58
|
On Monday 27 November 2006 19:47, Oleg Broytmann wrote: > On Mon, Nov 27, 2006 at 07:04:33PM +0100, Diez B. Roggisch wrote: > > class User(SQLObjec): > > ... > > > > def _init(self, *args, **kwargs): > > if <the_table_row_is_created>: > > co_object =3D CoObject(userID=3Dself.id) > > return super(User, self)._init(*args, **kwargs) > > > > This will ensure there is a CoObject whenever there is a User. > > _init() is called during creation, so you can be sure the row has not > been inserted into the DB yet, and there is no is. You need to change the > order of operations: > > def _init(self, *args, **kwargs): > super(User, self)._init(*args, **kwargs) # Perform INSERT and > get the id co_object =3D CoObject(userID=3Dself.id) Ok, I tried your suggestion - this is the code: class Guide(User): def _init(self, *args, **kwargs): super(Guide, self)._init(*args, **kwargs) # Perform INSERT and get = the=20 id user_name =3D self.user_name name =3D I18NText() name['en'] =3D user_name name['de'] =3D user_name description =3D I18NText() description['en'] =3D user_name description['de'] =3D user_name =20 my_bookable =3D GuideBookable(handle=3Duser_name, name=3Dname,=20 description=3Ddescription, proportional_price=3Ddecimal.Decimal('0= '), fixed_price=3Ddecimal.Decimal('0'), quantity=3D1, bookable_quantity=3D1, customer_visible=3DFalse, guideID =3D self.id ) Works fine for the first time. However, if I do for example Guide.get(<the_id>) I get an error like this: model.py in _init(self, *args, **kwargs) 383 def _init(self, *args, **kwargs): 384 super(Guide, self)._init(*args, **kwargs) # Perform INSERT = and=20 get the id =2D-> 385 user_name =3D self.user_name 386 name =3D I18NText() 387 name['en'] =3D user_name So - it seem _init is called on reloading the object as well, not only on=20 creation time. Any suggestions? =2D-=20 >> Diez B. Roggisch >> Developer T +49 (30) 443 50 99 - 27 =46 +49 (30) 443 50 99 - 99 M +49 (179) 11 75 303 E die...@ar... >> artnology GmbH A Milastra=DFe 4 / D-10437 Berlin T +49 (30) 443 50 99 - 0 =46 +49 (30) 443 50 99 - 99 E in...@ar... I http://www.artnology.com |
From: Oleg B. <ph...@ph...> - 2006-11-28 18:45:41
|
On Tue, Nov 28, 2006 at 06:41:50PM +0100, Diez B. Roggisch wrote: > So - it seem _init is called on reloading the object as well, not only on > creation time. Any suggestions? _create() Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Diez B. R. <die...@ar...> - 2006-12-05 14:40:14
|
On Tuesday 28 November 2006 19:45, Oleg Broytmann wrote: > On Tue, Nov 28, 2006 at 06:41:50PM +0100, Diez B. Roggisch wrote: > > So - it seem _init is called on reloading the object as well, not only on > > creation time. Any suggestions? > > _create() Finally, I tried it today - and it worked great. So - any chance this gets documented somewhere? I really think the sqlobject-docs are lacking, and to me that is the greatest hurdle of all. I'm not afraid to step into code, but the problem is: if I don't know what to look for in there, things get difficult. It would be great for example to have some best-practices gathered - like self-refering objects, objects with several relations to the same other object (e.g. user + two kinds of addresses) and so on. I really prefer SO over sqlalchemy, because it gets me an easier start, and I prefer to have ORM instead of classic SQL with just a layer glued on top. And SO does a good job so far. So I'd like to see it improve in quality, and am willing to step in. Is there a wiki for example? Diez |
From: Oleg B. <ph...@ph...> - 2006-12-05 19:25:42
|
On Tue, Dec 05, 2006 at 03:40:01PM +0100, Diez B. Roggisch wrote: > I really think the sqlobject-docs are lacking It is, I admit. Unfortunately, I don't have enough time to work on code, even less to work on docs. And the stream of doc patches from users is really too small. :( Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |