Closed rebeccacremona closed 3 months ago
Hi
Thanks for the nice words!
The problem is that we're interfering with some internal parts of the Django ORM when we assing our own TreeQuery
as the query class which should be used.
.update()
runs query.chain(...)
which in turn overrides the query class used by Django:
https://github.com/django/django/blob/adae619426b6f50046b3daaa744db52989c9d6db/django/db/models/query.py#L1227
We could try replacing .update()
with our own method, but we'd probably require a TreeUpdateQuery
or something for that. This sounds quite involved to me (I may be wrong) so maybe a better approach would be to detect these conditions and error out in a more obvious way.
Addendum: I wonder if you could keep it in the database by using a subquery. This seems to work nicely:
>>> Page.objects.filter(id__in=p.descendants(include_self=True).values("id")).update(title="blub")
11
Nice that that works!
In our very specific situation, I ended up wanting to keep around a list of IDs I could reference later, so making two separate queries within a transaction ended up being perfect, but I have to imagine that the subquery approach would work best for others!
I have added tests which verify the behavior with .descendants().update()
in 73ee469f0b54c8434172cb56d4e232818af6b76f
It still doesn't work but at least we'll know if anything changes.
I have added an example to the docs describing how to work around this issue, and I'm going to close it as wontfix. I hope someone finds the time and energy to fix it for real (feel free to submit PRs!) but having a documented workaround is good enough for me.
First, thank you for this terrific library!
When migrating a project from django-mptt, I discovered that with
Django 4.2.13
anddjango-tree-queries 0.19.0
,node.descendants().update(...)
raisesdjango.db.utils.ProgrammingError
: the generated SQL is anUPDATE
that references the__tree
table, but does not include the SQL for building it. In comparison,node.ancestors().update(...)
splits the work into two queries, issuing aSELECT
then anUPDATE
.Reproduction
Workaround
We were able to work around this easily in our application by manually taking the same two-query approach as with
ancestors
: