7 | | I think this has some ties into #24267 where the idea would be that we'd introduce an `UnresolvedLookup(BaseExpression)` class initialized from `__init__(self, field, **lookup)` and that would store `F(field)` in its source expressions and thus allow `replace_expressions` to take place normally as `Q` would be storing `UnresolvedLookup(key_parts[0], key_parts[1:])` instead of tuple of the form `tuple[str, Any]` as children. All `UnresolvedLookup` would do in its `resolve_expressions` is what can be found in the trailing part of `Query.build_filter` today that calls `solve_lookup_type`, `resolve_lookup_value`, and `build_lookup` but it would behave like a normal expression and avoids all the hacks we have in place today that special case `Q` objects. |
| 7 | I think this has some ties into #24267 where the idea would be that we'd introduce an `UnresolvedLookup(BaseExpression)` class initialized from `__init__(self, field, **lookup)` and that would store `F(field)` in its source expressions and thus allow `replace_expressions` to take place normally as `Q` would be storing `UnresolvedLookup(key_parts[0], key_parts[1:])` instead of tuple of the form `tuple[str, Any]` as children. |
| 8 | |
| 9 | All `UnresolvedLookup` would do in its `resolve_expressions` is what can be found in the trailing part of `Query.build_filter` today that calls `solve_lookup_type`, `resolve_lookup_value`, and `build_lookup` but it would behave like a normal expression and avoids all the hacks we have in place today that special case `Q` objects. |