Hi Alan -
this idea has been mentioned before, and i have a mention about it in
the docs (probably should add to the FAQ). basically, if you are
playing around with the foreign key identifiers, SA's core ORM has no
awareness of that...its interaction with the database is much simpler
than that (it tries to be as simple as possible). it has no idea
about the meaning of a foreign key identifier until its inside of a
flush(). my impression is that it would be a lot more complicated,
and add significant latency to attribute operations, for it to
reconcile foreign key values as attributes are attached and detached
to each other. if we consider the other direction, such as if i say
x.user_id=27, and there is no 27 in the identity map..its ambiguous
what should happen then. I could do a lazy load (adds latency that
might not be desired), or throw an error message. But then, what if
you just assigned #27 as the primary key on a transient (unsaved)
user object...we arent tracking that either, as transient instances
dont have an "identity" until they are flushed. or #27 exists with
an identity but it was marked for deletion. There are a lot of
complicated conditions that immediately arise, and by keeping tabs on
all primary/foreign key values and their status in memory, we're
starting to duplicate the functionality of the entire database. as
soon as SA is duplicating functionality that is already in the
database, thats its primary "red flag" that its going down a path it
shouldnt be.
now, if someone were really ambitious, they could create their own
attribute plugins to attempt this functionality; it is reasonably
straightforward to add event handlers to the attributes created by
relation() (just not documented as of yet). if someone wants to get
into that, im not opposed; but its definitely something for an
extension or external project, since it would complicate and slow
down things considerably for it to be built in the core (and also i
dont think it would ever work completely the way someone expects).
- mike
On Aug 22, 2006, at 10:04 AM, Alan Franzoni wrote:
> Hello, I've found what I think is an unexpected behaviour in
> sqlalchemy; it
> has to do with mapped objects and foreign keys handling. Check out
> this
> snippet:
>
> #begin
> # -*- coding: iso-8859-1 -*-
> #main.py
>
> from sqlalchemy import *
>
> db = create_engine("sqlite://testdb.db")
>
>
> metadata = BoundMetaData(db)
>
> users = Table("users", metadata,
> Column("user_id", Integer, primary_key=True),
> Column("text", String),
> )
>
> addresses = Table("addresses", metadata,
> Column("address_id", Integer, primary_key=True),
> Column("user_id", Integer, ForeignKey("users.user_id"))
> )
>
> users.create(checkfirst=True)
> addresses.create(checkfirst=True)
>
> class User(object):
> pass
>
> class Address(object):
> pass
>
>
> def print_user_and_id(obj):
> print "user is %s, user_id is %s" % (obj.user, obj.user_id)
>
> Address.mapper = mapper(Address, addresses)
> User.mapper = mapper(User, users, properties = {"addresses":
> relation(Address, backref="user")})
>
> session = create_session(bind_to=db)
>
> trans = session.create_transaction()
>
> user1 = User()
> user1.user_id = 10
> user1.text = "Hello World"
>
> user2 = User()
> user2.user_id = 20
> user2.text = "Hello World 2"
>
> addr1 = Address()
>
> session.save(user1)
> session.save(user2)
> session.save(addr1)
>
> addr1.user_id = user1.user_id
>
> print_user_and_id(addr1)
>
> session.flush()
>
> print_user_and_id(addr1)
>
> session.refresh(addr1)
>
> print_user_and_id(addr1)
>
> addr1.user = user2
> addr1.user_id = 10
>
> print_user_and_id(addr1)
>
> session.flush()
>
> print_user_and_id(addr1)
> #end
>
> this is the output:
>
> user is None, user_id is 10
> user is None, user_id is 10
> user is <__main__.User object at 0x00C90030>, user_id is 10
> user is <__main__.User object at 0x00C90050>, user_id is 10
> user is <__main__.User object at 0x00C90050>, user_id is 20
>
>
> What I think is unexpected is the missing constant 'link' between the
> helper property (user), which accepts User objects, and the mapped
> property
> (user_id), which accepts integers. I would imagine that, if I
> changed the
> 'user' property, the 'user_id' would immediately reflect that
> change, and
> viceversa - after all, why not? I can't think of any possible
> drawback.
>
> This way, in order to get the correct values, I need to do a
> session.refresh(obj), which can be a bit messy (it's a bit of pain
> to do it
> again and again).
>
> Also, the final code snippet is not clear:
>
> addr1.user = user2
> addr1.user_id = 10
>
> In this case, it seems that the 'user' property has priority (when
> flushed,
> the addr1 object has a user_id of 20), even though the user_id gets
> set
> later; is it always the case or might this change depending on what
> code is
> written?
>
> IMHO the objects should either react immediately to a related property
> change, or they shouldn't be both directly accessible, e.g. I
> should only
> be able to use either user_id or user on an Address object at a
> time, not
> both.
>
> --
> Alan Franzoni <[EMAIL PROTECTED]>
> -
> Togli .xyz dalla mia email per contattarmi.
> Rremove .xyz from my address in order to contact me.
> -
> GPG Key Fingerprint:
> 5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
> -
> Blog: http://laterradeglieroi.verdiperronchi.com
>
>
> ----------------------------------------------------------------------
> ---
> Using Tomcat but need to do more? Need to support web services,
> security?
> Get stuff done quickly with pre-integrated technology to make your
> job easier
> Download IBM WebSphere Application Server v.1.0.1 based on Apache
> Geronimo
> http://sel.as-us.falkag.net/sel?
> cmd=lnk&kid=120709&bid=263057&dat=121642
> _______________________________________________
> Sqlalchemy-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users