я вот это понял что у вас связи узлов друг с другом как то зависят от положения или это не так?
cte(recursive=True)
class Nodes(db.Model):
__tablename__ = 'nodes'
id = db.Column(db.Integer, primary_key=True)
def __init__(self, *args, **kwargs):
super(Nodes, self).__init__(*args, **kwargs)
class Edges(db.Model):
__tablename__ = 'edges'
id = db.Column(db.Integer, primary_key=True)
source = db.Column(db.Integer, db.ForeignKey('nodes.id'))
target = db.Column(db.Integer, db.ForeignKey('nodes.id'))
_edge_idx = db.Index('edge_idx', 'source', 'target', unique=True)
def __init__(self, *args, **kwargs):
super(Edges, self).__init__(*args, **kwargs)
a1=await Edges.create(source=1,target=2)
a2=await Edges.create(source=1,target=3)
a3=await Edges.create(source=2,target=5)
a4=await Edges.create(source=2,target=6)
a5=await Edges.create(source=3,target=4)
a6=await Edges.create(source=3,target=5)
a7=await Edges.create(source=4,target=6)
a8=await Edges.create(source=7,target=8)
a9=await Edges.create(source=7,target=9)
a10=await Edges.create(source=8,target=9)
descendants = db.select([Edges.source, Edges.target]).where(Edges.source == 3).cte(recursive=True)
parents = descendants.alias()
edges = Edges.alias()
descendants = descendants.union(db.select([edges.source, edges.target]).where(edges.source == parents.c.target))
query = db.select([descendants.c.target, descendants.c.source]).select_from(descendants)
result = await query.distinct('target').gino.all()
print(result)
Видимо, вы недавно с python подружились.
class Edges(db.Model):
__tablename__ = 'edges'
id = db.Column(db.Integer, primary_key=True)
source = db.Column(db.Integer, db.ForeignKey('nodes.id'))
target = db.Column(db.Integer, db.ForeignKey('nodes.id'))
_edge_idx = db.Index('edge_idx', 'source', 'target', unique=True)
class Parent(db.Model):
__tablename__ = 'parents'
id = db.Column(db.Integer, primary_key=True)
def __init__(self, **kw):
super().__init__(**kw)
self._children = set()
@property
def children(self):
return self._children
@children.setter
def add_child(self, child):
self._children.add(child)
child._parents.add(self)
class Child(db.Model):
__tablename__ = 'children'
id = db.Column(db.Integer, primary_key=True)
def __init__(self, **kw):
super().__init__(**kw)
self._parents = set()
@property
def parents(self):
return self._parents
class ParentXChild(db.Model):
__tablename__ = 'parents_x_children'
parent_id = db.Column(db.Integer, db.ForeignKey('parents.id'))
child_id = db.Column(db.Integer, db.ForeignKey('children.id'))
query = Parent.outerjoin(ParentXChild).outerjoin(Child).select()
parents = await query.gino.load(
Parent.distinct(Parent.id).load(add_child=Child.distinct(Child.id))).all()
a b c
\ / \ |
d e f
|\ /
g h
|
i
Мне минималистичное решение представляется следующим: В браузере клиента есть библиотека на js, которая ловит Operation Transformation инструкции с сервера и реализует их в блоке textarea (или другом - не важно) а на бекенде просто слушается вебсокет соединение, по которому эти Operation Transformation инструкции просто рассылаются всем редактирующим документ пользователям. То есть в момент когда пользователь вносит изменения - они оборачиваются в инструкции, шлются на сервер, а оттуда всем подключенным клиентам. И затем в браузере этих клиентов интерпретируются при помощи той самой js библиотеки. И всё.
Основная проблема для меня состоит в самостоятельно написании библиотеки, которая бы оборачивала изменения в javascript инструкции - ее разработка тудоемкий и временизатратный процесс. пересылка же инструкций по websocket - не является проблемой