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