[orm-devel] Access to attributes before a query
Diedrich Vorberg
diedrich@tux4web.de
Sat, 16 Nov 2002 18:04:58 +0100
Hi Mike,
>However, new dbclass object instances do not have attributes matching
>the column names until after an insert / select or when explicitly
>initialized. i.e.
> g = Groups()
> g.name - will raise AttributeError
>
>if group_id:
> g = ds.select(Groups, group_id).fetchone()
>
># else create an instance
>else:
> g = Groups()
>
>I think (bear in mind I am still a relative Python newbie) that this
>kind of usage is more or less consistant with how someone might expect a
>persistence scheme to work.
If you run this program:
#!/usr/bin/env python
class thing: # a do nothing class
pass
aThing = thing()
print aThing.an_atribute
you'll get the same AttributeError, so this behaviour is consitant
with what you'd expect from python.
I can see your point however, that this seems a little absurd
considering that the class' (=the tables) attributes (columns) have
been previously defined using the columns dict.
Two questions to consider:
o if you expect an unset attribute to contain something, what should
it contain? None, 0 or "" or a previously defined default value?
o another problem I have thought about: SQL allows for the
definition of default values. Fixed default values would be no
problem to implement, but what about values that call a
SQL function like NOW() or NEXTVAL(some_sequence)? Should we make
a SELECT after each INSERT to retrieve this kind of data from the
db? We have to do a SELECT to get the NEXTVAL() for SERIAL or
AUTO INCREMENT columns anyway.
># populate a form with instance defaults or data if editing an existing
>record
>form.add_widget('hidden', 'id' , value=group_id)
>form.add_widget("string", "code", title="Code", value=g.code, size=20,
>required=1)
>self.add_widget("string", "name", title="Group name", value=g.name,
>size=20, required=1)
>self.add_widget("checkbox", "is_login_allowed",
>value=num_bool(g.is_login_allowed), title="Allow login?")
I've run accross the same problem. This is how my code looks:
if item.oid(): # the oid() function returns a PostgreSQL OID value or
# simply 1 if we don't use PostgreSQL. The function
# should probably be renamed/aliased isStored() or so.
# If the dbobj has not been inserted, yet, it will
# return None.
title = item.title
description = item.description
price = "%5.2f" % item.price
else:
title = ""
description = ""
price = "0.0"
# create form...
Also, bear in mind that
g = Groups()
ds.insert(g)
results in an SQL query as
INSERT INTO item () VALUES ()
which simply won't work. You need to populate the instance (dbobj)
with some data to get a valid query. The reason I did it this way is,
we can't just insert NULL for an unset column, because there is a
difference in inserting NULL and insering nothing. Take a relation
like this for instance (this is PostgreSQL btw):
CREATE TABLE TEST
(
id SERIAL,
test VARCHAR(20),
created TIMESTAMP DEFAULT NOW()
);
and then do
INSERT INTO test (test, created) VALUES (NULL, NULL);
INSERT INTO test (test) VALUES (NULL);
you'll get
test=# select * from test;
id | test | created
----+------+-------------------------------
3 | |
4 | | 2002-11-16 18:00:08.602113+01
(2 rows)
the first created an all-empty column, the latter did what we wanted.
Any comment or suggestions on how to deal with this kind of problem
is very welcome!
Diedrich
--
_..._ Diedrich Vorberg
.' '.
/ _ _ \ http://www.tux4web.de
| (o)_(o) | info@tux4web.de
\( ) / .---.
//'._.'\ \ / \ Internet Dienstleistungen
// . \ \ \.@-@./ und 'Consulting'.
|| . \ \ /`\_/`\
|\ : / | // _ \\ Linux Rules!
\ `) ' (` /_ | \ )|_
_)``".____,.'"` (_ /`\_`> <_/ \
) )'--'( ( \__/'---'\__/
'---` `---`