Is there a way to present a partial tree using Django-MPTT's {% recursetree %}
without retrieving the entire tree from database? I need to show the first 20 nodes encountered by a Depth First Search.
Either of these (which do not retrieve the full tree) cause an exception:
# resulting querySet passed to {% recursetree %} in template
Thing.objects.all()[:20]
# directly sliced in template
{% recursetree all_nodes|slice:":20" %}
AssertionError while rendering: Cannot reorder a query once a slice has been taken
.
This on the other hand does work, but retrieves the entire tree:
# resulting querySet passed to {% recursetree %} in template
list(Thing.objects.all())[:20]
How can I do this without retrieving the entire tree form the DB?
MPTT uses pre-order (which is a depth-first search already.) So all you need to do is add a limit to your queryset before passing it to recursetree.
MPTT calls order_by()
if you pass a queryset to recursetree
, but it can't do that if you pass a list. That behaviour is kind of confusing and has caused other people issues too.
I've created a ticket on MPTT to address this.
In the meantime, you can just do the slicing before the list() call:
list(Thing.objects.all()[:20])
That will do the limit in the database, then convert the queryset to a list, which you can pass to recursetree
without it trying to reorder things.