Search code examples
pythonflaskzodb

How to load ghosted objects with ZODB in python?


I am writing a REST interface with flask in python using ZODB for a storage.

This is my code for GET method:

@app.get("/queues")
def get_queues():
    connection = db.open()
    root = connection.root
    if (hasattr(root, QUEUES_COLLECTION)):
        myQueues = root()[QUEUES_COLLECTION].values()
        #for obj in myQueues:
        #    print(obj.title)
        jsonQueues = orjson.dumps([obj.__dict__ for obj in myQueues])
        connection.close()
        return jsonQueues
    connection.close()
    return "ERROR no queues"

When accessing [ipaddress]:[port]/queues I get [{}{}] as a response, which is due to ZODB loading objects as ghosts. I know I can load them by iterating through collection and accessing attributes (as shown within code comments), but is there a better way?


Solution

  • You are correct. ZODB initially loads objects as "ghosts" to optimize memory usage. These ghosts are placeholders for the actual object data and they become activated when you access an attribute.

    But iterating over all the objects to access their attributes is not the most efficient way if you only need some objects from your collection.

    ZODB offers the _p_activate() method to activate a ghost without accessing any of its attributes. If you know you need to work with all objects in a collection, you can explicitly call this method on each one like:

    @app.get("/queues")
    def get_queues():
        connection = db.open()
        root = connection.root
        if hasattr(root, QUEUES_COLLECTION):
            myQueues = root()[QUEUES_COLLECTION].values()
            for obj in myQueues:
                obj._p_activate()  # explicitly activate each object
            jsonQueues = orjson.dumps([obj.__dict__ for obj in myQueues])
            connection.close()
            return jsonQueues
        connection.close()
        return "ERROR no queues"