Thread: [SQLObject] column default value
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Andreas K. <an...@ko...> - 2005-09-09 12:54:23
|
Hi! I'd like to define a default for one of my classes: class Worktime(SQLObject): customer =3D ForeignKey("customer", default=3DWHATDOIPUTHERE) task =3D ForeignKey("task") ... Now every row of Worktime must have a customer that is not NULL/None, while the task assignment might be NULL/None (because it's not clear against what task some time will get billed, while it's clear for which customer the time was spent). Now, a _set_customer setter doesn't work, because it needs the corresponding .task value, and it seems that _set_customer doesn't get called by Worktime(...) Supplying a callable default value would seem to be ok, BUT the callable doesn't get any context (like arguments to the constructor, the row object). Andreas |
From: Oleg B. <ph...@ma...> - 2005-09-09 13:05:25
|
On Fri, Sep 09, 2005 at 02:53:05PM +0200, Andreas Kostyrka wrote: > class Worktime(SQLObject): > customer = ForeignKey("customer", default=WHATDOIPUTHERE) > task = ForeignKey("task") > Now, a _set_customer setter doesn't work, because it needs the > corresponding .task value And what? > and it seems that _set_customer doesn't get > called by Worktime(...) It must get called. What version of SQLObject? > Supplying a callable default value would seem to be ok, BUT the callable > doesn't get any context (like arguments to the constructor, the row > object). Should it? Should datetime.now (for example) gets the context? Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Andreas K. <an...@ko...> - 2005-09-10 07:30:22
|
Am Freitag, den 09.09.2005, 17:05 +0400 schrieb Oleg Broytmann: > On Fri, Sep 09, 2005 at 02:53:05PM +0200, Andreas Kostyrka wrote: > > class Worktime(SQLObject): > > customer =3D ForeignKey("customer", default=3DWHATDOIPUTHERE) > > task =3D ForeignKey("task") >=20 > > Now, a _set_customer setter doesn't work, because it needs the > > corresponding .task value >=20 > And what? Well, somehow a default value derived from another column would make much sense. Not only in this case but others too. >=20 > > and it seems that _set_customer doesn't get > > called by Worktime(...) >=20 > It must get called. What version of SQLObject? probably r915. >=20 > > Supplying a callable default value would seem to be ok, BUT the callabl= e > > doesn't get any context (like arguments to the constructor, the row > > object). >=20 > Should it? Should datetime.now (for example) gets the context? Well, datetime.now probably doesn't need the context. But other default definitions DO need access to other columns. Currently I can get the context only by inspecting the callstack and guessing ;) Andreas |
From: Oleg B. <ph...@ph...> - 2005-09-10 18:47:31
|
On Sat, Sep 10, 2005 at 09:29:17AM +0200, Andreas Kostyrka wrote: > Am Freitag, den 09.09.2005, 17:05 +0400 schrieb Oleg Broytmann: > > On Fri, Sep 09, 2005 at 02:53:05PM +0200, Andreas Kostyrka wrote: > > > class Worktime(SQLObject): > > > customer = ForeignKey("customer", default=WHATDOIPUTHERE) > > > task = ForeignKey("task") > > > > > Now, a _set_customer setter doesn't work, because it needs the > > > corresponding .task value > > > > And what? > Well, somehow a default value derived from another column would make > much sense. Not only in this case but others too. 1. I still do not understand why your _set_customer doesn't work, and what the .tash has to do with it. 2. Can you explain your wish in terms of SQL? Can you write a CREATE TABLE clause declaring a default value for a column that depends on another column? > > > and it seems that _set_customer doesn't get > > > called by Worktime(...) > > > > It must get called. What version of SQLObject? > probably r915. Fresh enough. Are you sure _set_customer doesn't get called? Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Andreas K. <an...@ko...> - 2005-09-12 08:41:04
|
Am Samstag, den 10.09.2005, 22:47 +0400 schrieb Oleg Broytmann: > On Sat, Sep 10, 2005 at 09:29:17AM +0200, Andreas Kostyrka wrote: > > Am Freitag, den 09.09.2005, 17:05 +0400 schrieb Oleg Broytmann: > > > On Fri, Sep 09, 2005 at 02:53:05PM +0200, Andreas Kostyrka wrote: > > > > class Worktime(SQLObject): > > > > customer =3D ForeignKey("customer", default=3DWHATDOIPUTHERE) > > > > task =3D ForeignKey("task") > > >=20 > > > > Now, a _set_customer setter doesn't work, because it needs the > > > > corresponding .task value > > >=20 > > > And what? > > Well, somehow a default value derived from another column would make > > much sense. Not only in this case but others too. >=20 > 1. I still do not understand why your _set_customer doesn't work, and > what the .tash has to do with it. > 2. Can you explain your wish in terms of SQL? Can you write a > CREATE TABLE clause declaring a default value for a column that depends o= n > another column? Probably not. I can write a __init__ method. The idea is trivial, but probably not 100% correct in the the sense of database normalization. There are basically two cases that are modeled by this: * you work some time for a customer, BUT you do not know against which task it will be booked at the end. * And afterwards it can be used to speed up lookups for times worked for a certain customer. >=20 > > > > and it seems that _set_customer doesn't get > > > > called by Worktime(...) > > >=20 > > > It must get called. What version of SQLObject? > > probably r915. >=20 > Fresh enough. Are you sure _set_customer doesn't get called? I'll try a smaller testcase to verify that it's not something else. ;) Ok, I've tested against 0.6 and r915. from sqlobject import * import os os.unlink("/tmp/stest") __connection__ =3D dbconnection.connectionForURI("sqlite:///tmp/stest") class Customer(SQLObject): name =3D StringCol() class Task(SQLObject): name =3D StringCol() class Test(SQLObject): customer =3D ForeignKey('Customer') task =3D ForeignKey('Task') def _set_customer(self, val): print "VAL", val self._SO_set_customer(val) Customer.createTable(ifNotExists=3DTrue) Task.createTable(ifNotExists=3DTrue) Test.createTable(ifNotExists=3DTrue) cust =3D Customer(name=3D"cust1") task =3D Task(name=3D"Task1") Test(customer=3Dcust, task=3Dtask) My understanding is, that it should print something, right? It does not :( Andreas |
From: Oleg B. <ph...@ph...> - 2005-09-12 09:14:53
|
On Mon, Sep 12, 2005 at 10:39:55AM +0200, Andreas Kostyrka wrote: > Test(customer=cust, task=task) > > My understanding is, that it should print something, right? > It does not :( Oops, really. Seems like a bug. I'll look into it... Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Oleg B. <ph...@ph...> - 2005-09-12 14:31:50
|
On Mon, Sep 12, 2005 at 10:39:55AM +0200, Andreas Kostyrka wrote: > from sqlobject import * > > import os > os.unlink("/tmp/stest") > __connection__ = dbconnection.connectionForURI("sqlite:///tmp/stest") > > class Customer(SQLObject): > name = StringCol() > > class Task(SQLObject): > name = StringCol() > > class Test(SQLObject): > customer = ForeignKey('Customer') > task = ForeignKey('Task') > def _set_customer(self, val): > print "VAL", val > self._SO_set_customer(val) > > Customer.createTable(ifNotExists=True) > Task.createTable(ifNotExists=True) > Test.createTable(ifNotExists=True) > cust = Customer(name="cust1") > task = Task(name="Task1") > > Test(customer=cust, task=task) > > My understanding is, that it should print something, right? > It does not :( I've found the source of the bug but havn't commited a patch yet. Ian, there is the code in ._create(): # First we do a little fix-up on the keywords we were # passed: for column in self.sqlmeta.columnList: # If a foreign key is given, we get the ID of the object # and put that in instead if kw.has_key(column.foreignName): kw[column.name] = getID(kw[column.foreignName]) del kw[column.foreignName] because of which .set() gets different parameters in cases Test(customer=cust, task=task) and Test.set(customer=cust, task=task) I'd like to remove that manipulation in the inner "if" (and fix the next "if" after it). This allow to call setters for ForeignKeys in .set() called from __init__()/_create(). Any opinion on this? The change seems rather big considering we are in beta... Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Oleg B. <ph...@ph...> - 2005-09-13 08:24:58
|
On Mon, Sep 12, 2005 at 06:31:22PM +0400, Oleg Broytmann wrote: > Ian, there is the code in ._create(): > > # First we do a little fix-up on the keywords we were > # passed: > for column in self.sqlmeta.columnList: > > # If a foreign key is given, we get the ID of the object > # and put that in instead > if kw.has_key(column.foreignName): > kw[column.name] = getID(kw[column.foreignName]) > del kw[column.foreignName] > > because of which .set() gets different parameters in cases > Test(customer=cust, task=task) > and > Test.set(customer=cust, task=task) > > I'd like to remove that manipulation in the inner "if" (and fix the next > "if" after it). This allow to call setters for ForeignKeys in .set() called > from __init__()/_create(). Any opinion on this? The change seems rather big considering we are in beta... Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Ian B. <ia...@co...> - 2005-09-13 15:29:32
|
Oleg Broytmann wrote: > On Mon, Sep 12, 2005 at 06:31:22PM +0400, Oleg Broytmann wrote: > >> Ian, there is the code in ._create(): >> >> # First we do a little fix-up on the keywords we were >> # passed: >> for column in self.sqlmeta.columnList: >> >> # If a foreign key is given, we get the ID of the object >> # and put that in instead >> if kw.has_key(column.foreignName): >> kw[column.name] = getID(kw[column.foreignName]) >> del kw[column.foreignName] >> >> because of which .set() gets different parameters in cases >>Test(customer=cust, task=task) >> and >>Test.set(customer=cust, task=task) >> >> I'd like to remove that manipulation in the inner "if" (and fix the next >>"if" after it). This allow to call setters for ForeignKeys in .set() called >>from __init__()/_create(). > > > Any opinion on this? The change seems rather big considering we are in > beta... Yeah, I'm still figuring out what the change really means. What exactly are you proposing to change it to? -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |
From: Oleg B. <ph...@ph...> - 2005-09-13 15:43:04
|
On Tue, Sep 13, 2005 at 10:29:05AM -0500, Ian Bicking wrote: > Yeah, I'm still figuring out what the change really means. What exactly > are you proposing to change it to? Simply delete it. The test suite passed. Index: sqlobject/main.py =================================================================== --- sqlobject/main.py (revision 978) +++ sqlobject/main.py (working copy) @@ -1189,13 +1189,13 @@ # If a foreign key is given, we get the ID of the object # and put that in instead - if kw.has_key(column.foreignName): - kw[column.name] = getID(kw[column.foreignName]) - del kw[column.foreignName] # Then we check if the column wasn't passed in, and # if not we try to get the default. - if not kw.has_key(column.name): + if not kw.has_key(column.name) and not kw.has_key(column.foreignName): default = column.default # If we don't get it, it's an error: Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Ian B. <ia...@co...> - 2005-09-13 15:51:05
|
Oleg Broytmann wrote: > On Tue, Sep 13, 2005 at 10:29:05AM -0500, Ian Bicking wrote: > >>Yeah, I'm still figuring out what the change really means. What exactly >>are you proposing to change it to? > > > Simply delete it. The test suite passed. Oh, I see, the logic to resolve foreign keys has been moved elsewhere (into .set(), right?) Then sure, I think it can go in. -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |
From: Oleg B. <ph...@ph...> - 2005-09-13 16:34:23
|
On Tue, Sep 13, 2005 at 10:50:38AM -0500, Ian Bicking wrote: > Oh, I see, the logic to resolve foreign keys has been moved elsewhere > (into .set(), right?) I remember that was one of the first things I did when I've got commiter privileges - merging two similar peices of code in ._create() and .set(). > Then sure, I think it can go in. Commited at the revision 988. A test case added to test_join.py. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Oleg B. <ph...@ph...> - 2005-09-13 16:35:39
|
On Mon, Sep 12, 2005 at 10:39:55AM +0200, Andreas Kostyrka wrote: > from sqlobject import * > > import os > os.unlink("/tmp/stest") > __connection__ = dbconnection.connectionForURI("sqlite:///tmp/stest") > > class Customer(SQLObject): > name = StringCol() > > class Task(SQLObject): > name = StringCol() > > class Test(SQLObject): > customer = ForeignKey('Customer') > task = ForeignKey('Task') > def _set_customer(self, val): > print "VAL", val > self._SO_set_customer(val) > > Customer.createTable(ifNotExists=True) > Task.createTable(ifNotExists=True) > Test.createTable(ifNotExists=True) > cust = Customer(name="cust1") > task = Task(name="Task1") > > Test(customer=cust, task=task) > > My understanding is, that it should print something, right? > It does not :( I think I've fixed this at the revision 988. Please try and report if it helps. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Shuying W. <wan...@gm...> - 2005-09-12 07:47:31
Attachments:
pgconnection.py.diff
|
Hi, It looks like there's a bug in postgres/pgconnection.py in the version in trunk which doesn't look like it's applicable in version 0.7b1. I've included a diff here if someone would like to look into it. --Shuying |
From: Oleg B. <ph...@ph...> - 2005-09-12 08:25:07
|
Hello! On Mon, Sep 12, 2005 at 05:47:24PM +1000, Shuying Wang wrote: > - dsn_dict["password"] = password > + dsn_dict["password"] = passwd I commited the fix at the revision 978. Thank you! Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |