Вы можете использовать get
метод экземпляра объекта, чтобы найти объект по комбинации значений первичного ключа.
Метод get
выполняет поиск в кэше и базе данных db_session
и возвращает None
, если объект не найден:
from pony import orm
db = orm.Database('sqlite', ':memory:')
class Point(db.Entity):
x = orm.Required(int)
y = orm.Required(int)
description = orm.Optional(str)
orm.PrimaryKey(x, y)
db.generate_mapping(create_tables=True)
points = [(1, 2, 'foo'), (3, 4, 'bar'), (1, 2, 'baz'), (5, 6, 'qux')]
with orm.db_session:
for a, b, s in points:
point = Point.get(x=a, y=b)
if point is None:
point = Point(x=a, y=b, description=s)
Метод get
также работает с дополнительными составными ключами .
Также вы можете искать экземпляр сущности, используя квадратные скобки и перехватывать исключение:
with orm.db_session:
try:
point = Point[10, 20]
except orm.ObjectNotFound:
point = Point(x=10, y=20)
Обновление: разъяснения по использованию патерна IdentityMap
PonyORM использует шаблон проектирования IdentityMap. Это означает, что все объекты одного и того же класса, загруженные или созданные внутри db_session
, индексируются значениями его первичного ключа. Невозможно несколько объектов одного класса с одним и тем же первичным ключом внутри одного db_session
. Если метод get
вызывается несколько раз с одним и тем же значением первичного ключа, он возвращает один и тот же экземпляр:
with db_session:
a = Point.get(x=10, y=20)
b = Point.get(x=10, y=20)
assert a is b # the same object!
То же самое относится к ситуации, когда вы просто создаете объект и затем пытаетесь get
объект с тем же первичным ключом: Pony вернет объект, который вы только что создали:
with db_session:
a = Point.get(x=10, y=20)
if a is None:
a = Point(x=10, y=20)
# later, in the same db_session:
b = Point.get(x=10, y=20)
assert a is b # the same object, not saved yet
С другой стороны, если вы попытаетесь создать два разных объекта с одним и тем же первичным ключом, вы получите сообщение об ошибке:
with db_session:
a = Point(x=10, y=20)
b = Point(x=10, y=20)
Traceback (most recent call last):
...
pony.orm.core.CacheIndexError: Cannot create Point: instance with primary key 10, 20 already exists
Также, если вы попытаетесь создать объект, который уже существует в базе данных, не проверив его, вы получите ошибку:
with db_session:
a = Point(x=30, y=40)
with db_session:
b = Point(x=30, y=40)
Traceback (most recent call last):
...
pony.orm.core.TransactionIntegrityError: Object Point[30, 40] cannot be stored in the database. IntegrityError: UNIQUE constraint failed: Point.x, Point.y
Чтобы избежать этой ошибки, вы можете проверить существование объекта с помощью get
перед созданием нового.