[sqlalchemy] Re: I can replace an object with another in python, by changing the object dict to the other object dict. How does it settle with sqlalchemy? Does it works when another mapped object
I have talked to my customers, and they agreed that your solution is great. To match their demands, I've changed two things: 1. If the object exists in the db during construction than it's returned, else the object returned is a new object (that isn't returned). 2. All the attributes that identifies the object, are read-only, so I don't have to worry about them changing the identity of the object (Which may cause an unpredicted behaviour) SO THANK! On 4 דצמבר, 03:59, Michael Bayer [EMAIL PROTECTED] wrote: On Dec 3, 2008, at 6:39 PM, [EMAIL PROTECTED] wrote: B. So I can settle with a merge() method that returns anobject. I think it's the only solution (beside forcing them to work with saving to the db). Actually, it's not too bad. But it's also not easy, I tell you, to write such a function. Because what happens if one of the things that defines me, a part of my uniqueness, is not really a unique field, but a list of objects that are connected to me in a many- to-many relationship from another table. And what if I need to call merge() on each one of them. And what if two of them are evaluated to be the sameobject, so I need to fix the list. oof! merge() doesn't do much that you couldn't do manually on your own. if you need to write a jacked up merge()-like function that compares collections and things, i dont think Python will let you down in that regard. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: I can replace an object with another in python, by changing the object dict to the other object dict. How does it settle with sqlalchemy? Does it works when another mapped object
SQLAlchemy instruments classes using an event-based system that intercepts all setattribute and collection mutation operations, and logs these events as things to be reconciled when the Session is flushed. Additionally, the __dict__ of the object itself is referenced by the InstanceState object which is SQLAlchemy's per- object manager. Thirdly, the InstanceState object itself is placed inside of the __dict__ of every object instance, and this cannot be shared among multiple objects. So for these three reasons and probably more, using the old Python trick of replacing __dict__ will lead to poor results. To populate the state of an object with that of another, use a setattr() based approach: for k in dir(object1): setattr(object2, k, getattr(object1, k)) On Dec 3, 2008, at 3:47 PM, [EMAIL PROTECTED] wrote: The reason I'm doing so, is to solve the following problem: I have an object that is compounded from the fields - obj_id, num1, num2, num3. obj_id is my primary key. I want to create a save method for the object's class, that will do the following: If the object is in the session, save it. Else, if there is another object in the db with the same num1 and num2, use the object in the db instead of the current one, and warn the user if num3 is different. So it's quite like merge, but not necessarily on the primary key. Now, I want that use the object in the db wouldn't be by returning the object after the merge (original object if didn't exist, and db_object if existed), but really replacing it (self.dict = existing_object.dict), so one can use that object afterwards, without being confused. the most straightforward way to accomplish this would be a custom __new__ method, so that when you say: x = MyObject(num1=x, num2=y) the __new__() would do the session work to find the old object and return that instead, if present. There is a usage recipe on the Wiki that does something like this, except its 0.4 specific, and uses a metaclass in combination with a homegrown cache - I wrote it years ago and it can be done much more simply. Just use __new__(). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: I can replace an object with another in python, by changing the object dict to the other object dict. How does it settle with sqlalchemy? Does it works when another mapped object
A. Thanks for this great idea. From your suggestion, I realize that if I am going to use the new method, than I must enforce my __new__ (and __init__) to get all the unique fields as arguments. Then, if the object already exists in the db to return it, and otherwise save the new object. An important part of it is save the new object, because if I won't save the object, and one would do something like: obj1 = MyObject(num1 = x, num2 = y) obj1.save() obj2 = MyObject(num1 = x, num2 = x) obj2.num2 = y obj2.save() Then obj2 would not really be merged with obj1, and I will get a constraint exception - the thing my customers afraid of the most. So far, so good. But my customers are really weird, and two weeks ago they asked me to totally change the design of my project, so they will be able to use my mapped objects, without saving them to the db. Meaning, they wants to be able to do the following thing: 1. Create many MyObject instances. 2. Do some operations on them. (The features that my program supply) 3. Save some of them to the db, if they are interesting, but most of them, just throw away, without even saving them in the first place. The reason they asked it, is because in some of the cases, they will want to only use the classes in the API that I provide, for stuff that aren't important enough to be saved in the db, and without suffering from the overhead of saving objects to the db. So the case that I mentioned above with changing the attribute num2 can happen. Another option, is not to allow them to change num2, unless the object is saved already in the db. (using property) It would be weird. B. So I can settle with a merge() method that returns an object. I think it's the only solution (beside forcing them to work with saving to the db). Actually, it's not too bad. But it's also not easy, I tell you, to write such a function. Because what happens if one of the things that defines me, a part of my uniqueness, is not really a unique field, but a list of objects that are connected to me in a many- to-many relationship from another table. And what if I need to call merge() on each one of them. And what if two of them are evaluated to be the same object, so I need to fix the list. oof! On 3 דצמבר, 23:25, Michael Bayer [EMAIL PROTECTED] wrote: SQLAlchemy instruments classes using an event-based system that intercepts all setattribute and collection mutation operations, and logs these events as things to be reconciled when the Session is flushed. Additionally, the __dict__ of the object itself is referenced by the InstanceState object which is SQLAlchemy's per- object manager. Thirdly, the InstanceState object itself is placed inside of the __dict__ of every object instance, and this cannot be shared among multiple objects. So for these three reasons and probably more, using the old Python trick of replacing __dict__ will lead to poor results. To populate the state of an object with that of another, use a setattr() based approach: for k in dir(object1): setattr(object2, k, getattr(object1, k)) On Dec 3, 2008, at 3:47 PM, [EMAIL PROTECTED] wrote: The reason I'm doing so, is to solve the following problem: I have an object that is compounded from the fields - obj_id, num1, num2, num3. obj_id is my primary key. I want to create a save method for the object's class, that will do the following: If the object is in the session, save it. Else, if there is another object in the db with the same num1 and num2, use the object in the db instead of the current one, and warn the user if num3 is different. So it's quite like merge, but not necessarily on the primary key. Now, I want that use the object in the db wouldn't be by returning the object after the merge (original object if didn't exist, and db_object if existed), but really replacing it (self.dict = existing_object.dict), so one can use that object afterwards, without being confused. the most straightforward way to accomplish this would be a custom __new__ method, so that when you say: x = MyObject(num1=x, num2=y) the __new__() would do the session work to find the old object and return that instead, if present. There is a usage recipe on the Wiki that does something like this, except its 0.4 specific, and uses a metaclass in combination with a homegrown cache - I wrote it years ago and it can be done much more simply. Just use __new__(). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: I can replace an object with another in python, by changing the object dict to the other object dict. How does it settle with sqlalchemy? Does it works when another mapped object
On Dec 3, 2008, at 6:39 PM, [EMAIL PROTECTED] wrote: B. So I can settle with a merge() method that returns an object. I think it's the only solution (beside forcing them to work with saving to the db). Actually, it's not too bad. But it's also not easy, I tell you, to write such a function. Because what happens if one of the things that defines me, a part of my uniqueness, is not really a unique field, but a list of objects that are connected to me in a many- to-many relationship from another table. And what if I need to call merge() on each one of them. And what if two of them are evaluated to be the same object, so I need to fix the list. oof! merge() doesn't do much that you couldn't do manually on your own. if you need to write a jacked up merge()-like function that compares collections and things, i dont think Python will let you down in that regard. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---