Thread: [SQLObject] Thoughts on joins...
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Ian B. <ia...@co...> - 2005-10-10 03:09:10
|
I was thinking, why does SQLObject have joins at all? Why don't we just do: class Foo(SQLObject): bar = ForeignKey('Bar') class Bar(SQLObject): def _get_foos(self): return Foo.select(barID=self.id) Sure, we can call this pattern a "join" and give it a constructor. But is there *anything* additional that MultipleJoin does? There's only a *little* more that RelatedJoin does -- and most of that is stuff it *should* do, not what it does right now anyway. Anyway, just throwing out a thought. Ian |
From: Koen B. <ko...@ma...> - 2005-10-10 09:53:40
Attachments:
smime.p7s
|
And this way, the queries are more efficient too (see my other mail). On 10-okt-2005, at 5:09, Ian Bicking wrote: > I was thinking, why does SQLObject have joins at all? Why don't we > just do: > > class Foo(SQLObject): > bar = ForeignKey('Bar') > > class Bar(SQLObject): > def _get_foos(self): > return Foo.select(barID=self.id) > > Sure, we can call this pattern a "join" and give it a constructor. > But > is there *anything* additional that MultipleJoin does? There's only a > *little* more that RelatedJoin does -- and most of that is stuff it > *should* do, not what it does right now anyway. > > Anyway, just throwing out a thought. > > Ian > > > ------------------------------------------------------- > This SF.Net email is sponsored by: > Power Architecture Resource Center: Free content, downloads, > discussions, > and more. http://solutions.newsforge.com/ibmarch.tmpl > _______________________________________________ > sqlobject-discuss mailing list > sql...@li... > https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss > |
From: Kevin D. <da...@gm...> - 2005-10-11 13:52:32
|
On 10/9/05, Ian Bicking <ia...@co...> wrote: > I was thinking, why does SQLObject have joins at all? Why don't we just = do: > > class Foo(SQLObject): > bar =3D ForeignKey('Bar') > > class Bar(SQLObject): > def _get_foos(self): > return Foo.select(barID=3Dself.id) Makes sense to me. Kevin |
From: Jeff W. <je...@me...> - 2005-10-11 14:07:37
|
Kevin Dangoor wrote: > On 10/9/05, Ian Bicking <ia...@co...> wrote: > >>I was thinking, why does SQLObject have joins at all? Why don't we just do: >> >>class Foo(SQLObject): >> bar = ForeignKey('Bar') >> >>class Bar(SQLObject): >> def _get_foos(self): >> return Foo.select(barID=self.id) > > > Makes sense to me. > > Kevin On the other hand, it is rather nice to be able to call: Bar.addFoo( myFoo ) In addition, how would manually defined functions like this interact with schema generation? One of the features I *really* like about SQLObject is the way it will automatically create my schema for me. -- Jeff Watkins http://metrocat.org/ |
From: Koen B. <ko...@ma...> - 2005-10-11 15:24:51
|
I am writing this GUI app for multiple people working on one database. If I have a list of objects, I check which one should be updated by comparin= g the update datetime column with the datetime on which we did the last check. This works nice. But what is a nice way to set the update field with datetime.now() if ANY field gets update in an object? I don't want to override every _set function in an object :-) Koen |
From: Jorge G. <go...@ie...> - 2005-10-11 15:36:00
|
"Koen Bok" <ko...@ma...> writes: > But what is a nice way to set the update field with datetime.now() if ANY > field gets update in an object? I don't want to override every _set > function in an object :-) Isn't it possible to use a trigger on the database side? -- Jorge Godoy <go...@ie...> |
From: Koen B. <ko...@ma...> - 2005-10-11 18:00:41
Attachments:
smime.p7s
|
Although triggers are nice, I would like to have it database independent. On 11-okt-2005, at 17:32, Jorge Godoy wrote: > "Koen Bok" <ko...@ma...> writes: > > >> But what is a nice way to set the update field with datetime.now() >> if ANY >> field gets update in an object? I don't want to override every _set >> function in an object :-) >> > > Isn't it possible to use a trigger on the database side? > > -- > Jorge Godoy <go...@ie...> > > > > ------------------------------------------------------- > This SF.Net email is sponsored by: > Power Architecture Resource Center: Free content, downloads, > discussions, > and more. http://solutions.newsforge.com/ibmarch.tmpl > _______________________________________________ > sqlobject-discuss mailing list > sql...@li... > https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss > |
From: Jorge G. <go...@ie...> - 2005-10-11 18:29:25
|
Koen Bok <ko...@ma...> writes: > Although triggers are nice, I would like to have it database=20=20 > independent. The documentation has a solution for this, then: =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D Col Class: Specifying Columns =2D---------------------------- (...) `default`: The default value for this column. Used when creating a new row. If you give a callable object or function, the function will be called, and the return value will be used. So you can give ``DateTime.now`` to make the default value be the current time. Or you can use ``SQLBuilder.func.NOW()`` to have the database use the ``NOW()`` function internally. If you don't give a default there will be an exception if this column isn't specified in the call to `new`. (...) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D I think this solves your problem. You can use "datetime" (<http://python.org/doc/current/lib/module-datetime.html>) as well as mx.DateTime (<http://www.egenix.com/files/python/mxDateTime.html>) for this= .=20 =2D-=20 Jorge Godoy <go...@ie...> |
From: Oleg B. <ph...@ma...> - 2005-10-11 19:06:34
|
On Tue, Oct 11, 2005 at 03:23:56PM -0300, Jorge Godoy wrote: > I think this solves your problem. You can use "datetime" > (<http://python.org/doc/current/lib/module-datetime.html>) as well as > mx.DateTime (<http://www.egenix.com/files/python/mxDateTime.html>) for this. The `default` function will only be called upon INSERT, not UPDATE. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Koen B. <ko...@ma...> - 2005-10-11 20:03:48
Attachments:
smime.p7s
|
Erm, like this? (Sorry to bother you this much) class Person(SQLObject): def set(self): self.updated = datetime.now() return self.set firstname = UnicodeCol() updated = DateTimeCol() On 11-okt-2005, at 21:52, Oleg Broytmann wrote: > On Tue, Oct 11, 2005 at 09:18:49PM +0200, Koen Bok wrote: > >> Yeah, but wouldn't that mean that I have to override _set_key for >> each key in the object? Because I'd like to sync the updated field on >> any key update in the object. >> > > No, you only need to do this once in your overriden .set(), > before you > call parent's .set(). > > Oleg. > -- > Oleg Broytmann http://phd.pp.ru/ > ph...@ph... > Programmers don't die, they just GOSUB without RETURN. > |
From: Koen B. <ko...@ma...> - 2005-10-12 10:23:37
Attachments:
smime.p7s
|
This works, but only if I do multiple updates at once. And I'd like to update fields one by one. So I tried to override _SO_setValue, but if (of course) gives an error when I try to update (which calls itself in a loop) within the object. class Person(SQLObject): def set(self, **kw): self.updated = default=datetime.now() SQLObject.set(self, **kw) def _SO_setValue(self, name, value, from_python, to_python): self.updated = default=datetime.now() SQLObject._SO_setValue(self, name, value, from_python, to_python) updated = DateTimeCol(default=datetime.now()) On 11-okt-2005, at 21:52, Oleg Broytmann wrote: > On Tue, Oct 11, 2005 at 09:18:49PM +0200, Koen Bok wrote: > >> Yeah, but wouldn't that mean that I have to override _set_key for >> each key in the object? Because I'd like to sync the updated field on >> any key update in the object. >> > > No, you only need to do this once in your overriden .set(), > before you > call parent's .set(). > > Oleg. > -- > Oleg Broytmann http://phd.pp.ru/ > ph...@ph... > Programmers don't die, they just GOSUB without RETURN. > |
From: Koen B. <ko...@ma...> - 2005-10-12 10:28:33
Attachments:
smime.p7s
|
Wohoo I got it! This did the trick. class Person(SQLObject): def _SO_setValue(self, name, value, from_python, to_python): if not name == "updated": self.updated = default=datetime.now() SQLObject._SO_setValue(self, name, value, from_python, to_python) updated = DateTimeCol(default=datetime.now()) firstname = UnicodeCol() On 12-okt-2005, at 12:23, Koen Bok wrote: > This works, but only if I do multiple updates at once. And I'd like > to update fields one by one. So I tried to override _SO_setValue, > but if (of course) gives an error when I try to update (which calls > itself in a loop) within the object. > > class Person(SQLObject): > > def set(self, **kw): > self.updated = default=datetime.now() > SQLObject.set(self, **kw) > > def _SO_setValue(self, name, value, from_python, to_python): > self.updated = default=datetime.now() > SQLObject._SO_setValue(self, name, value, from_python, > to_python) > > updated = DateTimeCol(default=datetime.now()) > > On 11-okt-2005, at 21:52, Oleg Broytmann wrote: > >> On Tue, Oct 11, 2005 at 09:18:49PM +0200, Koen Bok wrote: >> >>> Yeah, but wouldn't that mean that I have to override _set_key for >>> each key in the object? Because I'd like to sync the updated >>> field on >>> any key update in the object. >>> >> >> No, you only need to do this once in your overriden .set(), >> before you >> call parent's .set(). >> >> Oleg. >> -- >> Oleg Broytmann http://phd.pp.ru/ >> ph...@ph... >> Programmers don't die, they just GOSUB without RETURN. >> > |
From: Koen B. <ko...@ma...> - 2005-10-12 11:16:49
Attachments:
smime.p7s
|
Ok, the next step is to try to update all changed objects on a select query. For this I will implement a new selectUpdate method. Bu t I keep getting these strange errors TypeError: unbound method selectUpdate() must be called with Order instance as first argument (got nothing instead) I don't get it, because I am clearly including self as the first argument. """ This is the part to enable automatic updating of changed objects """ updated = DateTimeCol(default=datetime.now()) lastUpdateCheck = datetime.now() def _SO_setValue(self, name, value, from_python, to_python): if not name == "updated": self.updated = default=datetime.now() SQLObject._SO_setValue(self, name, value, from_python, to_python) def selectUpdate(self,**kw): results = self.select(self,**kw) for item in results: if item.updated > self.lastUpdateCheck: item.sync() self.lastUpdateCheck = datetime.now() return results On 12-okt-2005, at 12:28, Koen Bok wrote: > Wohoo I got it! This did the trick. > > class Person(SQLObject): > > def _SO_setValue(self, name, value, from_python, to_python): > if not name == "updated": > self.updated = default=datetime.now() > SQLObject._SO_setValue(self, name, value, from_python, > to_python) > > updated = DateTimeCol(default=datetime.now()) > > firstname = UnicodeCol() > > > On 12-okt-2005, at 12:23, Koen Bok wrote: > >> This works, but only if I do multiple updates at once. And I'd >> like to update fields one by one. So I tried to override >> _SO_setValue, but if (of course) gives an error when I try to >> update (which calls itself in a loop) within the object. >> >> class Person(SQLObject): >> >> def set(self, **kw): >> self.updated = default=datetime.now() >> SQLObject.set(self, **kw) >> >> def _SO_setValue(self, name, value, from_python, to_python): >> self.updated = default=datetime.now() >> SQLObject._SO_setValue(self, name, value, from_python, >> to_python) >> >> updated = DateTimeCol(default=datetime.now()) >> >> On 11-okt-2005, at 21:52, Oleg Broytmann wrote: >> >>> On Tue, Oct 11, 2005 at 09:18:49PM +0200, Koen Bok wrote: >>> >>>> Yeah, but wouldn't that mean that I have to override _set_key for >>>> each key in the object? Because I'd like to sync the updated >>>> field on >>>> any key update in the object. >>>> >>> >>> No, you only need to do this once in your overriden .set(), >>> before you >>> call parent's .set(). >>> >>> Oleg. >>> -- >>> Oleg Broytmann http://phd.pp.ru/ >>> ph...@ph... >>> Programmers don't die, they just GOSUB without RETURN. >>> >> > |
From: Oleg B. <ph...@ph...> - 2005-10-12 11:22:49
|
On Wed, Oct 12, 2005 at 01:16:38PM +0200, Koen Bok wrote: > TypeError: unbound method selectUpdate() must be called with Order > instance as first argument (got nothing instead) > def selectUpdate(self,**kw): And how do you call it? Order.selectUpdate()? > results = self.select(self,**kw) results = self.select(**kw) > for item in results: > if item.updated > self.lastUpdateCheck: > item.sync() > self.lastUpdateCheck = datetime.now() > return results Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Koen B. <ko...@ma...> - 2005-10-12 11:26:15
Attachments:
smime.p7s
|
On 12-okt-2005, at 13:22, Oleg Broytmann wrote: > On Wed, Oct 12, 2005 at 01:16:38PM +0200, Koen Bok wrote: > >> TypeError: unbound method selectUpdate() must be called with Order >> instance as first argument (got nothing instead) >> > > >> def selectUpdate(self,**kw): >> > > And how do you call it? Order.selectUpdate()? Yep like that. To be exact: visibleOrders = list(Order.selectUpdate()) >> results = self.select(self,**kw) >> > > results = self.select(**kw) Same error. >> for item in results: >> if item.updated > self.lastUpdateCheck: >> item.sync() >> self.lastUpdateCheck = datetime.now() >> return results >> > > Oleg. > -- > Oleg Broytmann http://phd.pp.ru/ > ph...@ph... > Programmers don't die, they just GOSUB without RETURN. > > > ------------------------------------------------------- > This SF.Net email is sponsored by: > Power Architecture Resource Center: Free content, downloads, > discussions, > and more. http://solutions.newsforge.com/ibmarch.tmpl > _______________________________________________ > sqlobject-discuss mailing list > sql...@li... > https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss > |
From: Oleg B. <ph...@ph...> - 2005-10-12 11:32:59
|
On Wed, Oct 12, 2005 at 01:26:06PM +0200, Koen Bok wrote: > > And how do you call it? Order.selectUpdate()? > > Yep like that. To be exact: > > visibleOrders = list(Order.selectUpdate()) You call .selectUpdate() on the class, not an Order instance. You have to declare it a classmethod. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Oleg B. <ph...@ph...> - 2005-10-12 11:13:13
|
On Wed, Oct 12, 2005 at 12:23:21PM +0200, Koen Bok wrote: > This works, but only if I do multiple updates at once. Multiple updates can consists of 1 update, too! :) self.set(name=value) Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Ian B. <ia...@co...> - 2005-10-12 15:33:13
|
Oleg Broytmann wrote: > On Wed, Oct 12, 2005 at 12:23:21PM +0200, Koen Bok wrote: > >>This works, but only if I do multiple updates at once. > > > Multiple updates can consists of 1 update, too! :) > > self.set(name=value) And you can save a query: def _SO_setValue(...): if not name == 'updated': self.set({name: value, 'updated': datetime.now()}) ... -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |
From: Koen B. <ko...@ma...> - 2005-10-12 15:41:50
Attachments:
smime.p7s
|
This rocks! For anyone who is trying to do the same, here is the magic: Attach this to any SQLObject class and you can replace updated objects by calling Foo.cacheUpdate() """ This is the part to enable automatic updating of changed objects """ updated = DateTimeCol(default=datetime.now()) lastUpdateCheck = datetime.now() def _SO_setValue(self, name, value, from_python, to_python): if not name == 'updated': self.set({name: value, 'updated': datetime.now()}) SQLObject._SO_setValue(self, name, value, from_python, to_python) def cacheUpdate(self): updatedObjects = list(self.select(self.q.updated > self.lastUpdateCheck)) for object in updatedObjects: object.sync() self.lastUpdateCheck = datetime.now() cacheUpdate = classmethod(cacheUpdate) On 12-okt-2005, at 17:32, Ian Bicking wrote: > Oleg Broytmann wrote: > >> On Wed, Oct 12, 2005 at 12:23:21PM +0200, Koen Bok wrote: >> >>> This works, but only if I do multiple updates at once. >>> >> Multiple updates can consists of 1 update, too! :) >> self.set(name=value) >> > > And you can save a query: > > def _SO_setValue(...): > if not name == 'updated': > self.set({name: value, 'updated': datetime.now()}) > ... > > > > -- > Ian Bicking / ia...@co... / http://blog.ianbicking.org > > > ------------------------------------------------------- > This SF.Net email is sponsored by: > Power Architecture Resource Center: Free content, downloads, > discussions, > and more. http://solutions.newsforge.com/ibmarch.tmpl > _______________________________________________ > sqlobject-discuss mailing list > sql...@li... > https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss > |
From: Oleg B. <ph...@ma...> - 2005-10-12 16:18:16
|
On Wed, Oct 12, 2005 at 05:41:39PM +0200, Koen Bok wrote: > def cacheUpdate(self): > updatedObjects = list(self.select(self.q.updated > > self.lastUpdateCheck)) > for object in updatedObjects: > object.sync() > self.lastUpdateCheck = datetime.now() > > cacheUpdate = classmethod(cacheUpdate) There is a convention to name the first parameter in classmethods 'cls' or 'klass', not 'self'. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Koen B. <ko...@ma...> - 2005-10-12 16:24:56
Attachments:
smime.p7s
|
I was too fast. With this code I get a: TypeError: set() takes exactly 1 argument (2 given) Strange, while there is only one dict passed. def _SO_setValue(self, name, value, from_python, to_python): if not name == 'updated': self.set({name: value, 'updated': datetime.now()}) SQLObject._SO_setValue(self, name, value, from_python, to_python) > There is a convention to name the first parameter in classmethods > 'cls' > or 'klass', not 'self'. That would make this, right? def cacheUpdate(cls=self): updatedObjects = list(self.select(self.q.updated > self.lastUpdateCheck)) for object in updatedObjects: object.sync() self.lastUpdateCheck = datetime.now() cacheUpdate = classmethod(cacheUpdate) Sorry, but I am not such a Python master (yet!). |
From: Ian B. <ia...@co...> - 2005-10-12 16:27:48
|
Koen Bok wrote: > I was too fast. With this code I get a: > > *TypeError: set() takes exactly 1 argument (2 given)* > * > * > Strange, while there is only one dict passed. > > def _SO_setValue(self, name, value, from_python, to_python): > if not name == 'updated': > self.set({name: value, 'updated': datetime.now()}) Oops, that should be self.set(**{...}) The first argument is the hidden "self" argument, hence two arguments. -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |
From: Oleg B. <ph...@ph...> - 2005-10-12 16:32:52
|
On Wed, Oct 12, 2005 at 06:24:43PM +0200, Koen Bok wrote: > I was too fast. With this code I get a: > > TypeError: set() takes exactly 1 argument (2 given) > > Strange, while there is only one dict passed. > > def _SO_setValue(self, name, value, from_python, to_python): > if not name == 'updated': > self.set({name: value, 'updated': datetime.now()}) self.set(**{name: value, 'updated': datetime.now()}) > SQLObject._SO_setValue(self, name, value, from_python, > to_python) > > >There is a convention to name the first parameter in classmethods > >'cls' > >or 'klass', not 'self'. > > That would make this, right? No. Just replace 'self' with 'cls': def cacheUpdate(cls): updatedObjects = list(cls.select(cls.q.updated > cls.lastUpdateCheck)) for object in updatedObjects: object.sync() cls.lastUpdateCheck = datetime.now() cacheUpdate = classmethod(cacheUpdate) > Sorry, but I am not such a Python master (yet!). This is why I am pointing you to different directions on an every step of the conversation. :) Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Koen B. <ko...@ma...> - 2005-10-12 16:41:06
Attachments:
smime.p7s
|
Well all those directions have led to this wonderfull piece of code :-) I had to add an else otherwise it still updated twice (duh) Now my interface is super-speedy© AND up-to-date© Thanks! """ This is the part to enable automatic updating of changed objects """ updated = DateTimeCol(default=datetime.now()) lastUpdateCheck = datetime.now() def _SO_setValue(self, name, value, from_python, to_python): if not name == 'updated': self.set(**{name: value, 'updated': datetime.now()}) else: SQLObject._SO_setValue(self, name, value, from_python, to_python) def cacheUpdate(cls): updatedObjects = list(cls.select(cls.q.updated > cls.lastUpdateCheck)) for object in updatedObjects: object.sync() cls.lastUpdateCheck = datetime.now() cacheUpdate = classmethod(cacheUpdate) On 12-okt-2005, at 18:32, Oleg Broytmann wrote: > On Wed, Oct 12, 2005 at 06:24:43PM +0200, Koen Bok wrote: > >> I was too fast. With this code I get a: >> >> TypeError: set() takes exactly 1 argument (2 given) >> >> Strange, while there is only one dict passed. >> >> def _SO_setValue(self, name, value, from_python, to_python): >> if not name == 'updated': >> self.set({name: value, 'updated': datetime.now()}) >> > > self.set(**{name: value, 'updated': datetime.now()}) > > >> SQLObject._SO_setValue(self, name, value, from_python, >> to_python) >> >> >>> There is a convention to name the first parameter in classmethods >>> 'cls' >>> or 'klass', not 'self'. >>> >> >> That would make this, right? >> > > No. Just replace 'self' with 'cls': > > def cacheUpdate(cls): > updatedObjects = list(cls.select(cls.q.updated > > cls.lastUpdateCheck)) > for object in updatedObjects: > object.sync() > cls.lastUpdateCheck = datetime.now() > cacheUpdate = classmethod(cacheUpdate) > > >> Sorry, but I am not such a Python master (yet!). >> > > This is why I am pointing you to different directions on an > every step > of the conversation. :) > > Oleg. > -- > Oleg Broytmann http://phd.pp.ru/ > ph...@ph... > Programmers don't die, they just GOSUB without RETURN. > |
From: Oleg B. <ph...@ph...> - 2005-10-12 17:46:59
|
On Wed, Oct 12, 2005 at 06:41:00PM +0200, Koen Bok wrote: > if not name == 'updated': > self.set(**{name: value, 'updated': datetime.now()}) > else: > SQLObject._SO_setValue(self, name, value, from_python, to_python) It is also recommended not to write negative conditions in 'if'. Either write if name != 'updated': or even better if name == 'updated': SQLObject._SO_setValue(self, name, value, from_python, to_python) else: self.set(**{name: value, 'updated': datetime.now()}) PS. "not to write negative conditions" should be saied "to avoid negative conditions"! (-: Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |