How to create instance of a table entry but not added in ponyorm

ghz 昨天 ⋅ 4 views

How to create instance of a table entry but not added in ponyorm?

How can I use a create an instance of a table definition without inserting a row to the corresponding Table.

For example what I would like is:

from pony import orm
from pony.orm import Required
db = orm.Database()
class User(db.Entity):
    name = Required(str)
    address = Optional(str)

db.bind(provider='sqlite', filename=':memory:')
db.generate_mapping(create_tables=True)

bob = User(name='bob')

### CODE FROM HERE ON IS WRONG BUT SHOWCASES WHAT I WANT
# So far the database has not been modified
bob.add() # at this point bob is added
db.commit() # transaction is committed

Is the above possible? The reason I want this is that I want to use the class definition without adding items to the database. It's just a very easy clean way of making sure that Users everywhere (in this example) have the same attributes.

I was initially using pyDAL which I found very easy to set up tables but there I would have to define the tables and then also write the classes so I moved to ponyorm but it's unclear if I can achieve what I'd like.

thank you

UPDATE 1:

An example usecase for this is:

  • I'm scraping a website
  • I pull in "row" data
  • if address is not yet available
    • Create an instance of the User
    • Not add it just use the class as a container for the data
  • If the information is available
    • Create an instance and only if the record doesn't already exist add it

Basically I want to be able to use the Class as a container of the information without always having to add it to the database.

Answer

In Pony ORM, you can indeed create an instance of an entity (such as User) without inserting it into the database, and it will not persist in the database until you explicitly call add() and commit().

The way Pony ORM works, when you create an instance of an entity, the instance itself is not immediately added to the database until you explicitly invoke add() and commit(). This allows you to work with the entity instances as Python objects without worrying about immediately writing them to the database.

Key Concept:

  • Creating the Instance: When you create an entity instance (User(name='bob')), Pony ORM treats it as an in-memory object and does not automatically add it to the database.
  • Adding to the Database: You can later add the object to the database by calling add() and committing the transaction using db.commit(). Until then, the object is not persisted.

Here is an updated example that demonstrates how you can achieve what you want:

Example:

from pony import orm
from pony.orm import Required, Optional

# Set up the database and define the User entity
db = orm.Database()

class User(db.Entity):
    name = Required(str)
    address = Optional(str)

# Bind to an in-memory SQLite database
db.bind(provider='sqlite', filename=':memory:')
db.generate_mapping(create_tables=True)

# Create an instance without adding it to the database
bob = User(name='bob')

# At this point, 'bob' is an in-memory instance and has not been added to the database
print(bob)  # This will print the object, but not its DB values

# Now let's commit it to the database
db.commit()  # This will persist 'bob' into the database

Explanation:

  • Creating the instance: bob = User(name='bob') creates an instance of User that is not yet persisted in the database.
  • Database commit: The db.commit() is necessary to persist bob to the database. Until this point, the bob object is just a normal Python object.
  • Adding manually: If you don't call add() explicitly, the object won't be inserted into the database.

Addressing your use case:

For your specific use case (scraping data and storing only if certain conditions are met), you can follow the same approach.

Here’s an enhanced use case example:

# Simulate scraping data
scraped_data = [{'name': 'bob', 'address': None},
                {'name': 'alice', 'address': '123 Main St'}]

# Loop through scraped data and create User instances as needed
for data in scraped_data:
    # Check if address is missing
    if data['address'] is None:
        user_instance = User(name=data['name'])  # Create instance without adding to DB
        print(f"Created in-memory user: {user_instance.name}")
    else:
        # Check if user already exists in DB (this can be a query)
        existing_user = User.get(name=data['name'])
        if existing_user is None:
            user_instance = User(name=data['name'], address=data['address'])
            db.commit()  # Persist to the database
            print(f"Added {user_instance.name} to the database.")
        else:
            print(f"User {data['name']} already exists.")

Key Points:

  1. Creating in-memory objects: You can create instances of your entities without adding them to the database immediately. You simply create the objects and leave them in-memory until you decide to commit them.

  2. Querying and conditional inserts: If you only want to add a User to the database when it doesn't already exist, you can query the database (using User.get(...) or other queries) and check the result. If no matching object is found, you can commit the new instance to the database.

  3. Database Commit: The commit() method is where the actual insertion into the database happens. If you don't call commit(), the object is just in memory and not persisted.

Alternative: Using db_session

If you prefer, you can use a db_session context to manage transactions, which would allow you to create entities in memory, inspect them, and commit them conditionally, without manually invoking commit():

from pony.orm import db_session

# Create an in-memory session where we don't commit unless we explicitly do so
with db_session:
    # Create user objects (they're not added to DB yet)
    user = User(name="bob")
    
    # Add logic to conditionally commit
    if some_condition:
        db.commit()  # Add to DB if needed

This pattern allows for more flexibility, especially when working with conditions or external data sources, like your web scraping example. You can control when changes are committed to the database and keep your entities in memory for as long as needed.

Conclusion:

In Pony ORM, you can indeed create objects and treat them as in-memory containers without adding them to the database. You control when to persist them using the commit() method. This makes it a clean and flexible approach for working with entities without unnecessary immediate database writes.