Hello everybody, I have a problem with a list of object references. I wrote a product that buffers a list of objects. The list is created with self.LIST = self.restrictedTraverse(ListOfPaths).objectValues['MyOtherProduct'])) inside a function called "charge_buffer". This product also has a DTMLFile named "show_list". "show_list" contains: <dtml-var LIST> When I open "show_list" in my browser I can see the list like this: [<MyOtherProduct instance at ecdcfa8>, <MyOtherProduct instance at ecdd050>, etc. ] (This seems to be a list of addresses) As a result I can use "LIST" in an in-tag in another DTMLFile called "use_list": <dtml-in LIST> <dtml-var id><br> </dtml-in> This seems to work very well. When I open "use_list" in my browser I see a list of ids. But when I reload "use_list" 3 or 4 times I suddenly get an attribute error for "get", just as if the sequence-item wasn't an object anymore. The same thing happens when I refresh my product or restart the server. (BTW. my product inherits from Persistant, and I set _p_changed=1 after charging the buffer) So I repeatedly called "charge_buffer" and looked at "show_list" and "use_list". "use_list" always showed me the same list of id's, as I expectet, but "show_list" always showed me a different list where the adresses where always different. It seems that the "addresses" of my object instances change a view seconds after loading my buffer. As a result I am unable to save a list of object references for later use. Can anybody help me with this? Thanks in advance Sven Rudolph -- Sven Rudolph, Programmierer GermanMedicalServices.de GmbH Unter den Eichen 5, 65195 Wiesbaden Tel.: 06 11 / 97 46 25 2
On Mon, Aug 12, 2002 at 12:39:09PM +0200, Sven Rudolph wrote:
It seems that the "addresses" of my object instances change a view seconds after loading my buffer. As a result I am unable to save a list of object references for later use.
I don't know why the addresses seem to change, that's weird. But it's probably not a good idea to make such a list persistent anyway. You *should* be able to cache them for a little while but they should be dynamically generated when zope starts, at the very least, because the IDs WILL change if you do such things as delete & recreate one of the objects, or do an import of a backup, etc... Instead, it's probably better to save a list of *paths* (either absolute, or just names to acquire), and get the IDs when you need them, possibly cacheing for performance. There's an example of this kind of thing in the source for PortableHole which I was just looking at. -- Paul Winkler "Welcome to Muppet Labs, where the future is made - today!"
Hello Paul, thanks for your quick reply!
It seems that the "addresses" of my object instances change a view seconds after loading my buffer. As a result I am unable to save a list of object references for later use. URGGHH. I meant "a few seconds" :-(
...You *should* be able to cache them for a little while... It is possible, but the cache turns invalid after a few minutes.
...but they should be dynamically generated when zope starts, at the very least, because the IDs WILL change if you do such things as delete & recreate one of the objects, or do an import of a backup, etc... I am planning to regenerate this list every 24h, or manualy via management screen when I need it. I do this because of performance reasons, because dynamically generating the list is far to slow.
Instead, it's probably better to save a list of *paths*... That's what I'm doing now. The list is an attribut of my buffer product. After generation it is allready sorted and sliced to my needs (the whole process takes about 1 minute - PIII800MHz,1,5GByteRAM). I want to use this list in an in-tag, but with paths i have to do it like this: <dtml-in MY_BUFFER_INSTANCE prefix=x> <dtml-var "restrictedTraverse(x_item).id"><p> </dtml-in>
This works, but it is to slow. I want to cache the object references directly in my buffer, without the need of calling restrictedTraverse in the in-tag. BTW: I forgot to say that I'm using Zope-2.5.1 with Python-2.1.3 Greetings Sven -- Sven Rudolph, Programmierer GermanMedicalServices.de GmbH Unter den Eichen 5, 65195 Wiesbaden Tel.: 06 11 / 97 46 25 2
Sven Rudolph writes:
... I wrote a product that buffers a list of objects. The list is created with self.LIST = self.restrictedTraverse(ListOfPaths).objectValues['MyOtherProduct'])) inside a function called "charge_buffer".
This product also has a DTMLFile named "show_list". "show_list" contains: <dtml-var LIST>
When I open "show_list" in my browser I can see the list like this: [<MyOtherProduct instance at ecdcfa8>, <MyOtherProduct instance at ecdd050>, etc. ] You should be very careful with this:
Most Zope objects you handle are acquisition wrappers. These are not persistent (even if the base objects are) and cannot be stored in ZODB. When you want to make them persistent, you need to strip down the wrapper before storing and wrap again on access, something like: self.LIST= [o.aq_base for o in self.restrictedTraverse(...)...] def getLIST(self): return [o.__of__(self) for o in self.LIST]
... This seems to work very well. When I open "use_list" in my browser I see a list of ids. But when I reload "use_list" 3 or 4 times I suddenly get an attribute error for "get", just as if the sequence-item wasn't an object anymore. I do not understand it.
Instead, you should have gotten an "Unpicklable Error".
The same thing happens when I refresh my product or restart the server. Obviously, your objects are not pickled correctly.
I wonder why they did at all. Dieter
Hello Dieter, thank you for your reply!
...When I open "show_list" in my browser I can see the list like this: [<MyOtherProduct instance at ecdcfa8>, <MyOtherProduct instance at ecdd050>, etc. ] You should be very careful with this:
Most Zope objects you handle are acquisition wrappers. What does that mean?
When you want to make them persistent, you need to strip down the wrapper before storing and wrap again on access, something like:
self.LIST= [o.aq_base for o in self.restrictedTraverse(...)...]
def getLIST(self): return [o.__of__(self) for o in self.LIST] Hmm..I can't follow you :-(
... This seems to work very well. When I open "use_list" in my browser I see a list of ids. But when I reload "use_list" 3 or 4 times I suddenly get an attribute error for "get", just as if the sequence-item wasn't an object anymore. I do not understand it.
Instead, you should have gotten an "Unpicklable Error".
The same thing happens when I refresh my product or restart the server. Obviously, your objects are not pickled correctly. As far as I can see it, LIST is stored correctly, but the values in LIST are not valid for more then (let's say) 5 minutes.
I wonder why they did at all.
Maybe you have a different suggestion for me? Let me repeat my problem: I have several folders wich contain instances of several (news) products. There are about 12.000 product instances of 6 (or more) products in 6 (or more) folders. I must put them in one single list, sort this list by "validfrom" (an instance of DateTime inside each product instance) and then return the first 100 entrys in this list. This resulting list must contain references and it must be cacheable. Or in shorter words: I need a list of references of the newest news on our site. Greetings Sven -- Sven Rudolph, Programmierer GermanMedicalServices.de GmbH Unter den Eichen 5, 65195 Wiesbaden Tel.: 06 11 / 97 46 25 2
This sounds very much like a job for ZCatalog(s). Stefan On Dienstag, August 13, 2002, at 02:33 , Sven Rudolph wrote:
Maybe you have a different suggestion for me? Let me repeat my problem: I have several folders wich contain instances of several (news) products. There are about 12.000 product instances of 6 (or more) products in 6 (or more) folders. I must put them in one single list, sort this list by "validfrom" (an instance of DateTime inside each product instance) and then return the first 100 entrys in this list. This resulting list must contain references and it must be cacheable. Or in shorter words: I need a list of references of the newest news on our site.
Hello Stefan, thanks for your suggestion!
This sounds very much like a job for ZCatalog(s).
ZCatalog doesn't contain object references. It only contains static data. But I need a list of references for further use. Greetings Sven
Stefan
On Dienstag, August 13, 2002, at 02:33 , Sven Rudolph wrote:
Maybe you have a different suggestion for me? Let me repeat my problem: I have several folders wich contain instances of several (news) products. There are about 12.000 product instances of 6 (or more) products in 6 (or more) folders. I must put them in one single list, sort this list by "validfrom" (an instance of DateTime inside each product instance) and then return the first 100 entrys in this list. This resulting list must contain references and it must be cacheable. Or in shorter words: I need a list of references of the newest news on our site.
-- Sven Rudolph, Programmierer GermanMedicalServices.de GmbH Unter den Eichen 5, 65195 Wiesbaden Tel.: 06 11 / 97 46 25 2
Sven Rudolph wrote:
ZCatalog doesn't contain object references. It only contains static data. But I need a list of references for further use.
What you are suggesting is an "expensive" operation. You need to wake up 12000 objects or more to make the complete list. The ZCatalog was created so you don't need to do that. Just do the query in the catalog, sort on date, and then get the newest objects from that list. You can get the object from a catalog item bycalling : catalog.getobject(rid, REQUEST) regards Max M -- "Sorry I would Really Like To Help More On This Project, But Am To Busy Doing Paid Work On A Tight Deadline" Max M
Sven Rudolph writes:
Most Zope objects you handle are acquisition wrappers. What does that mean? Please read the "Acquisition" section of
<http://www.dieter.handshake.de/pyprojects/zope/book/chap3.html> Dieter
participants (5)
-
Dieter Maurer -
Max M -
Paul Winkler -
Stefan H. Holek -
Sven Rudolph