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