querysets.py 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. from __future__ import unicode_literals
  2. from utilities.sql import NullsFirstQuerySet
  3. class PrefixQuerySet(NullsFirstQuerySet):
  4. def annotate_depth(self, limit=None):
  5. """
  6. Iterate through a QuerySet of Prefixes and annotate the hierarchical level of each. While it would be preferable
  7. to do this using .extra() on the QuerySet to count the unique parents of each prefix, that approach introduces
  8. performance issues at scale.
  9. Because we're adding a non-field attribute to the model, annotation must be made *after* any QuerySet
  10. modifications.
  11. """
  12. queryset = self
  13. stack = []
  14. for p in queryset:
  15. try:
  16. prev_p = stack[-1]
  17. except IndexError:
  18. prev_p = None
  19. if prev_p is not None:
  20. while (p.prefix not in prev_p.prefix) or p.prefix == prev_p.prefix:
  21. stack.pop()
  22. try:
  23. prev_p = stack[-1]
  24. except IndexError:
  25. prev_p = None
  26. break
  27. if prev_p is not None:
  28. prev_p.has_children = True
  29. stack.append(p)
  30. p.depth = len(stack) - 1
  31. if limit is None:
  32. return queryset
  33. return list(filter(lambda p: p.depth <= limit, queryset))