Add Lot.parents
This commit is contained in:
parent
aa52367f03
commit
f7112d7fe1
|
@ -2,9 +2,9 @@ import uuid
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from flask import g
|
from flask import g
|
||||||
|
from sqlalchemy import TEXT
|
||||||
from sqlalchemy.dialects.postgresql import UUID
|
from sqlalchemy.dialects.postgresql import UUID
|
||||||
from sqlalchemy.orm import aliased
|
from sqlalchemy.sql import expression as exp
|
||||||
from sqlalchemy.sql import expression
|
|
||||||
from sqlalchemy_utils import LtreeType
|
from sqlalchemy_utils import LtreeType
|
||||||
from sqlalchemy_utils.types.ltree import LQUERY
|
from sqlalchemy_utils.types.ltree import LQUERY
|
||||||
from teal.db import UUIDLtree
|
from teal.db import UUIDLtree
|
||||||
|
@ -53,22 +53,32 @@ class Lot(Thing):
|
||||||
Path.add(self.id, child)
|
Path.add(self.id, child)
|
||||||
db.session.refresh(self) # todo is this useful?
|
db.session.refresh(self) # todo is this useful?
|
||||||
|
|
||||||
def remove_child(self, child: 'Lot'):
|
def remove_child(self, child):
|
||||||
|
if isinstance(child, Lot):
|
||||||
Path.delete(self.id, child.id)
|
Path.delete(self.id, child.id)
|
||||||
|
else:
|
||||||
|
assert isinstance(child, uuid.UUID)
|
||||||
|
Path.delete(self.id, child)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def children(self):
|
def children(self):
|
||||||
"""The children lots."""
|
"""The children lots."""
|
||||||
# From https://stackoverflow.com/a/41158890
|
# From https://stackoverflow.com/a/41158890
|
||||||
# todo test
|
id = UUIDLtree.convert(self.id)
|
||||||
cls = self.__class__
|
|
||||||
exp = '*.{}.*{{1}}'.format(UUIDLtree.convert(self.id))
|
|
||||||
child_lots = aliased(Lot)
|
|
||||||
|
|
||||||
return self.query \
|
return self.query \
|
||||||
.join(cls.paths) \
|
.join(self.__class__.paths) \
|
||||||
.filter(Path.path.lquery(expression.cast(exp, LQUERY))) \
|
.filter(Path.path.lquery(exp.cast('*.{}.*{{1}}'.format(id), LQUERY)))
|
||||||
.join(child_lots, Path.lot)
|
|
||||||
|
@property
|
||||||
|
def parents(self):
|
||||||
|
"""The parent lots."""
|
||||||
|
id = UUIDLtree.convert(self.id)
|
||||||
|
i = db.func.index(Path.path, id)
|
||||||
|
parent_id = db.func.replace(exp.cast(db.func.subpath(Path.path, i - 1, i), TEXT), '_', '-')
|
||||||
|
join_clause = parent_id == exp.cast(Lot.id, TEXT)
|
||||||
|
return self.query.join(Path, join_clause).filter(
|
||||||
|
Path.path.lquery(exp.cast('*{{1}}.{}.*'.format(id), LQUERY))
|
||||||
|
)
|
||||||
|
|
||||||
def __contains__(self, child: 'Lot'):
|
def __contains__(self, child: 'Lot'):
|
||||||
return Path.has_lot(self.id, child.id)
|
return Path.has_lot(self.id, child.id)
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Lot(Thing):
|
||||||
def add_child(self, child: Union[Lot, uuid.UUID]):
|
def add_child(self, child: Union[Lot, uuid.UUID]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def remove_child(self, child: Lot):
|
def remove_child(self, child: Union[Lot, uuid.UUID]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -42,6 +42,10 @@ class Lot(Thing):
|
||||||
def children(self) -> LotQuery:
|
def children(self) -> LotQuery:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parents(self) -> LotQuery:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Path:
|
class Path:
|
||||||
id = ... # type: Column
|
id = ... # type: Column
|
||||||
|
|
|
@ -12,6 +12,5 @@ class Lot(Thing):
|
||||||
name = f.String(validate=f.validate.Length(max=STR_SIZE), required=True)
|
name = f.String(validate=f.validate.Length(max=STR_SIZE), required=True)
|
||||||
closed = f.Boolean(missing=False, description=m.Lot.closed.comment)
|
closed = f.Boolean(missing=False, description=m.Lot.closed.comment)
|
||||||
devices = NestedOn(Device, many=True, dump_only=True)
|
devices = NestedOn(Device, many=True, dump_only=True)
|
||||||
children = NestedOn('Lot',
|
children = NestedOn('Lot', many=True, dump_only=True)
|
||||||
many=True,
|
parents = NestedOn('Lot', many=True, dump_only=True)
|
||||||
dump_only=True)
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ class LotBaseChildrenView(View):
|
||||||
lot = self.get_lot(id)
|
lot = self.get_lot(id)
|
||||||
self._post(lot, self.get_ids())
|
self._post(lot, self.get_ids())
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
ret = self.schema.jsonify(lot)
|
ret = self.schema.jsonify(lot)
|
||||||
ret.status_code = 201
|
ret.status_code = 201
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -210,10 +210,15 @@ def test_post_get_lot(user: UserClient):
|
||||||
|
|
||||||
def test_post_add_children_view(user: UserClient):
|
def test_post_add_children_view(user: UserClient):
|
||||||
"""Tests adding children lots to a lot through the view."""
|
"""Tests adding children lots to a lot through the view."""
|
||||||
l, _ = user.post(({'name': 'Parent'}), res=Lot)
|
parent, _ = user.post(({'name': 'Parent'}), res=Lot)
|
||||||
child, _ = user.post(({'name': 'Child'}), res=Lot)
|
child, _ = user.post(({'name': 'Child'}), res=Lot)
|
||||||
l, _ = user.post({}, res=Lot, item='{}/children'.format(l['id']), query=[('id', child['id'])])
|
parent, _ = user.post({},
|
||||||
assert l['children'][0]['id'] == child['id']
|
res=Lot,
|
||||||
|
item='{}/children'.format(parent['id']),
|
||||||
|
query=[('id', child['id'])])
|
||||||
|
assert parent['children'][0]['id'] == child['id']
|
||||||
|
child, _ = user.get(res=Lot, item=child['id'])
|
||||||
|
assert child['parents'][0]['id'] == parent['id']
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(reason='Just develop the test')
|
@pytest.mark.xfail(reason='Just develop the test')
|
||||||
|
|
Reference in New Issue