Deep Nesting Guide

This guide demonstrates the deep nesting capabilities of drf-nestedqueryfields. There is no fixed limit on nesting depth — the filter is applied recursively to every nested serializer.

Examples by Depth Level

Level 1: Basic Filtering

# Include only specific fields
GET /cities/?fields=name,code

# Exclude specific fields
GET /cities/?fields!=id,created_at

Level 2: One Level Deep

# Include nested fields
GET /cities/?fields=name,province.name,province.code

# Exclude nested fields
GET /cities/?fields!=id,province.id

Level 3: Two Levels Deep

# Include deeply nested fields
GET /cities/?fields=province.region.name,province.region.code

# Mixed depth includes
GET /cities/?fields=name,province.name,province.region.country.name

Level 4: Three Levels Deep

# Very deep nesting
GET /cities/?fields=province.region.country.name,province.region.country.code

# Exclude at deep levels
GET /cities/?fields!=province.region.country.id

Level 5: Four Levels Deep

# Full depth across the test model
GET /cities/?fields=province.region.country.continent.name

# Combining include with exclude
GET /cities/?fields=name,province.region.country.continent.name&fields!=province.id

When fields and fields! both reference the same name, exclude wins.

Beyond: Unknown or Non-existent Paths

Paths that don’t resolve to a real field — at any depth — are silently ignored. This keeps clients safe to request optional or speculative paths without server errors:

GET /cities/?fields=name,fake.level2.level3.level4.level5
GET /cities/?fields=name,path1.l2.l3,path2.l2.l3.l4.l5.l6.l7

Error Handling

The following malformed inputs are tolerated and produce no errors:

GET /cities/?fields=name,nonexistent.field
GET /cities/?fields=name,....                  # Stray dots
GET /cities/?fields=name,,province..region     # Empty parts

What gets ignored:

  • Non-existent field names at any level

  • Empty field specifications

  • Malformed dot notation

  • Fields that don’t exist on nested serializers

Implementation Details

Tree-Based Parsing

Field specifications like province.region.country.name are parsed into a nested tree:

{
    'province': {
        'region': {
            'country': {
                'name': True
            }
        }
    }
}

Recursive Processing

  • Each serializer level is processed independently

  • Nested serializers are filtered recursively

  • Non-existent paths are safely ignored

  • Work scales with the actual depth of the serializer tree, not the depth of the request specification

Test Coverage

The deep-nesting behaviour is exercised by:

  • tests/test_deep_nesting.py — depth 3-5 includes/excludes, mixed-depth operations, edge cases (empty specs, trailing dots), combined include/exclude.

  • tests/test_extreme_depth.py — very deep bogus paths, malformed specifications, large numbers of bogus fields.

  • tests/test_userfields_with_nested_modelserializers.py — original single-level suite plus added second-level cases.

Running the Tests

# Whole suite
pytest

# Just the deep-nesting suites
pytest tests/test_deep_nesting.py tests/test_extreme_depth.py