Relationships
Simple relationship
from corm import Storage, Entity, Nested
class Address(Entity):
street: str
number: int
class User(Entity):
name: str
address: Address = Nested(entity_type=Address)
storage = Storage()
john = User(
data={
'name': 'John',
'address': {
'street': 'First',
'number': 1,
},
},
storage=storage,
)
assert john.address.street == 'First'
assert john.address.number == 1
Bidirectional relationships
from corm import Storage, Entity, Relationship, Nested
class Address(Entity):
street: str
number: int
user: 'User' = Relationship(entity_type='User')
class User(Entity):
name: str
address: Address = Nested(
entity_type=Address,
back_relation=True,
)
storage = Storage()
john = User(
data={
'name': 'John',
'address': {
'street': 'First',
'number': 1,
},
},
storage=storage,
)
assert john.address.user == john
Self-nested
import typing as t
from corm import Storage, Entity, Relationship, Nested
class Item(Entity):
id: int
items: t.List['Item'] = Nested(
entity_type='Item',
back_relation=True,
many=True,
default=list,
)
parent: 'Item' = Relationship(entity_type='Item')
storage = Storage()
item1 = Item({'id': 1, 'items': [{'id': 2}, {'id': 3}]}, storage)
item2, item3 = item1.items
assert item1.id == 1
assert item1.parent is None
assert item2.id == 2
assert item2.parent == item1
assert item2.items == []
assert item3.id == 3
assert item3.parent == item1
assert item3.items == []
Change relationships between entities
from corm import Entity, Relationship, Nested, Storage
class Address(Entity):
street: str
user: 'User' = Relationship(entity_type='User')
class User(Entity):
id: int
address: Address = Nested(
entity_type=Address,
back_relation=True,
)
storage = Storage()
john = User(
data={
'id': 1,
'name': 'John',
'description': 'john smith',
'address': {
'street': 'kirova',
},
},
storage=storage,
)
old_address = john.address
assert old_address.user is john
address = Address(data={'street': 'lenina'}, storage=storage)
john.address = address
assert old_address.user is None
assert address.user == john
assert john.address is address
Also it works with many=True
import typing as t
from corm import Entity, Relationship, Nested, Storage
class Address(Entity):
street: str
user: 'User' = Relationship(entity_type='User')
class User(Entity):
id: int
addresses: t.List[Address] = Nested(
entity_type=Address,
back_relation=True,
many=True,
)
storage = Storage()
john = User(
data={
'id': 1,
'name': 'John',
'description': 'john smith',
'addresses': [
{
'street': 'kirova 1',
},
{
'street': 'kirova 2',
},
],
},
storage=storage,
)
old_address1, old_address2 = john.addresses
# you can change existing list
john.addresses.remove(old_address1)
assert old_address1.user is None
assert old_address2.user is john
john.addresses.clear()
assert old_address1.user is None
assert old_address2.user is None
assert john.addresses == []
new_address1 = Address(data={'street': 'lenina 1'}, storage=storage)
new_address2 = Address(data={'street': 'lenina 2'}, storage=storage)
john.addresses.append(new_address1)
assert new_address1.user is john
assert john.addresses == [new_address1]
john.addresses.extend([new_address2])
assert new_address2.user is john
assert john.addresses == [new_address1, new_address2]
# or completely replace it
john.addresses = [old_address1]
assert new_address1.user is None
assert new_address2.user is None
assert old_address1.user is john
Note
As you can see it changes both user and address, but keep in mind it is possible to change relationship through Nested
but not through Relationship
. In this example address.user = user
will raise ValueError
Manually related entities
It is not common case but is is able to use this way
from corm import Storage, Entity, Relationship, RelationType
storage = Storage()
class Address(Entity):
street: str
number: int
class User(Entity):
name: str
address: Address = Relationship(
entity_type=Address,
relation_type=RelationType.PARENT,
)
address = Address({'street': 'First', 'number': 1}, storage)
john = User({'name': 'John'}, storage)
storage.make_relation(
from_=john,
to_=address,
relation_type=RelationType.PARENT,
)
assert john.address == address