Skip to content

Conversation

Copilot
Copy link

@Copilot Copilot AI commented Sep 24, 2025

This PR implements add_related_count() method for TreeQuerySet as a direct replacement for django-mptt's method of the same name, enabling users to migrate from django-mptt while retaining the ability to count related objects across tree hierarchies.

Problem

Users migrating from django-mptt to django-tree-queries were missing the add_related_count() functionality, which annotates tree nodes with counts of related objects. The challenge was that django-mptt's approach relies on concrete database fields (like lft, rght), while django-tree-queries uses CTE-generated fields like tree_path that aren't accessible to Django's Subquery class.

Solution

The new implementation leverages django-tree-queries' existing CTE infrastructure and tree_path field to provide the same functionality:

# Non-cumulative counting (direct relationships only)
regions = Region.objects.add_related_count(
    Region.objects.all(),
    Site,
    'region',
    'site_count',
    cumulative=False
)

# Cumulative counting (includes descendants)  
regions_cumulative = Region.objects.add_related_count(
    Region.objects.all(),
    Site,
    'region', 
    'total_sites',
    cumulative=True
)

Key Features

  • Database Agnostic: Optimized for PostgreSQL using array operations (ANY(__tree.tree_path)), with fallback string operations for SQLite, MySQL, and MariaDB
  • Two Counting Modes: Non-cumulative (direct relationships) and cumulative (includes all descendants)
  • Automatic Relationship Detection: Intelligently finds reverse relationship names
  • CTE Integration: Uses existing tree_path field from recursive Common Table Expressions
  • Performance Optimized: Uses subqueries designed for each database backend

Implementation Details

The method works by:

  1. For non-cumulative counts: Simple annotation using Django's Count() with reverse relationships
  2. For cumulative counts: Using subqueries that leverage tree_path to find all descendants of each node, then counting related objects across the entire subtree

Testing

Added comprehensive test coverage including:

  • Test models (Region and Site) that mirror real-world usage scenarios
  • Non-cumulative counting validation
  • Cumulative counting with complex hierarchies (country → state → city structure)
  • Edge cases with empty trees

Documentation

Updated README.rst with:

  • Detailed usage examples showing both counting modes
  • Method signature documentation
  • Integration examples with existing tree query methods
  • Added to feature list

This provides a complete migration path for django-mptt users who rely on add_related_count() functionality.

Fixes #21.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@Copilot Copilot AI changed the title [WIP] Recommended replacement for django-mptt's add_related_count() method? Add add_related_count() method as replacement for django-mptt functionality Sep 24, 2025
@Copilot Copilot AI requested a review from matthiask September 24, 2025 11:17
Copilot finished work on behalf of matthiask September 24, 2025 11:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Recommended replacement for django-mptt's add_related_count() method?

2 participants