feincms / django-tree-queries

Adjacency-list trees for Django using recursive common table expressions. Supports PostgreSQL, sqlite, MySQL and MariaDB.
https://django-tree-queries.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
415 stars 27 forks source link

Support for Many-to-Many relationship #32

Closed sevdog closed 2 years ago

sevdog commented 2 years ago

I am developing a tree structure with "detachable" sub-trees, and for what I have seen the current TreeNode and TreeNodeForeignKey are not suited for this.

Nested trees

To accomplish this kind of structure I need to use a Many-to-Many parent (and also I need to define some extra fields on the M2M relation-table).

I do not need to query the whole graph, just individual trees (which can intersect with each other as shown in figure).

In MPTT I would have used the TreeManyToManyField, but since that project is not maintained I would like to accomplish something similar with this library.

I undestrand that it is not an easy step but I would like to see if it is feasable.

matthiask commented 2 years ago

Hi,

django-mptt's TreeManyToManyField is just a m2m field with some additional goodies and doesn't influence the core behavior of MPTT at all. It couldn't; django-mptt assumes that each node has at most one parent and django-tree-queries does the same.

The tree_depth and tree_path attributes of the nodes in query tree C are ambiguous depending on whether you come from A or B and are undefined when coming from A and B at the same time. So, as I see it, django-tree-queries can't help much without first thinking about the value these tree attributes should have.

--

But maybe I'm misunderstanding and you "just" need a many to many field where the label shows the tree structure somehow? It should be easy to extend django-tree-queries with a TreeNodeManyToManyField (see https://github.com/matthiask/django-tree-queries/blob/main/tree_queries/fields.py , there's not much there -- deconstruct avoids creating migrations when replacing a ForeignKey with a TreeNodeForeignKey, formfield only ensures that the model field uses the TreeNodeChoiceField form field). The TreeNodeMultipleChoiceField already exists https://github.com/matthiask/django-tree-queries/blob/main/tree_queries/forms.py

You could even do this in your own project. Or submit a pull request with the new model field.

sevdog commented 2 years ago

Hi @matthiask, thanks for your response.

To better explain my use case the trees I am willing to use are "Procedures", where each node is a precise step and which could be a sub-procedure. My aim is to have sub-procedures reusable, without duplicating their sub-tree. This is why current TreeNodeForeignKey, that is Many-to-One (leaves to root), poses a limit.

I understand that both depth and path are not absolute in this structure, since they depends on the entry-point (and now I realize that my drawing shows an "happy scenario", where depth of C is the same in both A and B).

Also I understand that having the same sub-tree used twice in a single tree could get the query a bit complicated and result not so easy to understand.

A -- X -- C
  \- Y -- Z -- C

I will look deeper to see how this kind of recursive query could be built, because to have a "deterministic" path and depth will require a join to handle the M2M.

sevdog commented 2 years ago

I have found that for my use-case the django-postgresql-dag could be a better suite. Since with an M2M the tree becomes a graph (I have re-read my graph-theory books and now I am starting hating to have accepted a feature which involves this elements).

matthiask commented 2 years ago

Great! Yes, a DAG library is the way to go, and this is quite definitely out of scope for django-tree-queries.