Add Foreign Key Filter Support in SearchBuilder#745
Open
Alwinator wants to merge 2 commits into
Open
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #745 +/- ##
===========================================
- Coverage 100.00% 99.88% -0.12%
===========================================
Files 86 87 +1
Lines 6848 7173 +325
===========================================
+ Hits 6848 7165 +317
- Misses 0 8 +8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Owner
|
Thanks @Alwinator for the PR, i like the proposition. I will review the code and merge if it looks good |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related Issues
What this does
This PR adds the ability to filter by foreign key (relation) fields directly in the DataTables SearchBuilder UI. Previously, relation fields (
HasOne/HasMany) only supportednull/!nullconditions in the SearchBuilder. Now they behave like string columns and support the full set of string conditions:=,!=,contains,starts,ends, and their negated counterparts.When a user types a search term (e.g. "John") for a relation column, the backend resolves it by searching across all string columns of the related model using case-insensitive matching. This effectively matches against what
__admin_repr__would show — so the filter feels intuitive from the user's perspective.How it works
stringtype columns, so users get a free-text input (no dropdown, no extra AJAX calls)..has()(forHasOne) or.any()(forHasMany) clauses withOR'dilikeconditions.not_contains,neq, etc.) useANDlogic so that a row is only excluded if none of the related model's string columns match.is_null/is_not_nullcontinue to work exactly as before.No frontend JS changes were needed — the existing
stringSearchBuilder type andextractCriteria()handle everything already since we're inserverSide: truemode.Performance escape hatch
For large datasets where searching all string columns on a related model might be expensive, there's a new
searchable_relation_fieldsoption:This restricts the generated query to only the specified columns instead of scanning every string column on the related model. By default (when not set), all string columns are searched.
Changes
starlette_admin/fields.py—RelationField.search_builder_typechanged from"default"to"string"starlette_admin/views.py— Addedsearchable_relation_fieldsattribute toBaseModelViewstarlette_admin/contrib/sqla/view.py— Relation fields are now included in the defaultsearchable_fieldslist (but still excluded fromsortable_fields);searchable_relation_fieldsis threaded through to the query builderstarlette_admin/contrib/sqla/helpers.py— New_relationship_string_filter()and_apply_string_operator()helpers;build_query()now detects string operators on relationship attributes and delegates accordinglytests/sqla/test_view_meta.py— Updated assertions to reflect that relation fields are now searchable by defaulttests/sqla/test_fk_filter.py— 28 new tests covering HasOne filters, HasMany filters, AND/OR combinations, thesearchable_relation_fieldsallowlist, reverse relations, case-insensitive matching, and multi-column searchScope
This PR only implements FK filtering for the SQLAlchemy backend (including SQLModel, which inherits it automatically). Support for ODMantic, MongoEngine, and Beanie is deferred to a follow-up — their converters would need similar treatment but the patterns differ enough to warrant separate work.
Testing
All existing SQLA tests continue to pass. The 28 new tests cover:
HasOnerelations (contains, eq, neq, startswith, endswith, and all negations)HasManyrelation filtering (uses.any()instead of.has())is_null/is_not_null(unchanged behavior, but verified alongside the new operators)searchable_relation_fieldsallowlist (verifying that excluded columns are truly not searched)