Repository navigation
Fix page.query in main() and query strings in TemplateRoute - #6942
Open
ndonkoHenri wants to merge 9 commits into
Open
ndonkoHenri wants to merge 9 commits into
ndonkoHenri wants to merge 9 commits into
Conversation
QueryString cached a URL that only route changes refreshed, so in main() page.query was empty for an app opened with a query string. Parse page.route on every read instead, which also stops percent-encoded values from being decoded twice.
page.query had a one-line entry on the Page reference and no page for its QueryString type, so get(), to_dict and path were documented nowhere. - Rewrite the QueryString class docstring and get()'s docstring in Google style; get() reads to_dict directly. - Add website/docs/types/querystring.md and its sidebar entry. - Add a "Query strings" section to the Navigation and Routing guide, and note that TemplateRoute should match page.query.path when routes carry a query string, since the last template parameter otherwise captures it.
TemplateRoute.match() ran the template against the whole route, query string included. The last parameter captured the query string (`/books/42?tab=reviews` gave `id == "42?tab=reviews"`), and a template without a trailing parameter didn't match at all (`/store?ref=ad` against `/store`), nor did any route whose query string contains a `/`. Match the part before the first `?`, as the declarative Router already does. QueryString now splits the route at the first `?` as well, instead of with urlsplit(), which reads a route starting with `//` as a host name. The routing guide's note to match `page.query.path` is replaced by a description of the new behavior.
The client builds page.route from the full URI, so a deep link or URL with a `#` fragment reaches Python as `/books/42?tab=reviews#details`. Splitting only at `?` put the fragment into the last query value, and TemplateRoute's last parameter captured it. Drop the fragment before splitting. Also document that parameters without a value (`?debug`, `?debug=`) are left out, and say in the routing guide that `page.query` reflects a navigation once the route has changed, e.g. in on_route_change.
Link API symbols with the xref form instead of relative page paths, and link `get()` in the Query strings section to QueryString.get. The `page.views` links now point at BasePage.views instead of the top of the Page reference.
q="flet" and page=2 read like the flet package and the page object. Use q="shoes", limit=20 and "salt & pepper" instead.
test_query_string.py opens a real Session the way the client connects and checks that page.query follows page.route in main(), in on_route_change and after later route changes, how the route splits into path, query and fragment, that push_route parameters read back decoded once, and that a query outliving its page is empty. test_template_route.py checks that templates match the route path whatever its query string and fragment, and that a failed match clears the previous parameters.
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The implementation is focused, documented, and covered by regression tests for the reported routing failures.
0 open findings
What changed in this PR
Fixes routing query parsing at startup and ensures route templates ignore query strings and fragments.
Changes:
- Parse
page.querydirectly from the current route. - Match
TemplateRouteagainst path-only routes. - Add documentation, changelog entries, and regression tests.
| File | Description |
|---|---|
CHANGELOG.md |
Records routing fixes and documentation. |
sdk/python/packages/flet/src/flet/controls/page.py |
Removes cached query refresh behavior. |
sdk/python/packages/flet/src/flet/controls/query_string.py |
Parses queries dynamically from page.route. |
sdk/python/packages/flet/src/flet/controls/template_route.py |
Excludes queries and fragments from matching. |
sdk/python/packages/flet/tests/test_query_string.py |
Tests startup, navigation, decoding, and lifetime behavior. |
sdk/python/packages/flet/tests/test_template_route.py |
Tests path-only template matching. |
website/docs/cookbook/navigation-and-routing.md |
Documents query strings and updates API links. |
website/docs/types/querystring.md |
Adds the QueryString API reference. |
website/sidebars.yml |
Adds QueryString to navigation. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Deploying flet-website-v2 with
|
| Latest commit: |
2ce3ae0
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://e2e93906.flet-website-v2.pages.dev |
| Branch Preview URL: | https://fix-page-query-initial-route.flet-website-v2.pages.dev |
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.
Fixes #5898
page.queryinmain()QueryStringkept its own copy of the URL, which only a route change refreshed (throughpage.query()). Before the first route change, so inmain(),page.query.to_dictwas{}andget()raisedKeyError. A web app opened at/?name=Joecouldn't readname.The stored copy caused two more bugs:
q=dom%26dogsread back asq="dom", andpush_route("/search", q="salt & pepper")asq="salt ".page.url + page.route, sopathandto_dictwere wrong whereverpage.urlisn't an http URL. On desktop,page.query.pathcame back as/tmp/flet.sock/store.QueryStringnow readspage.routeevery time. It drops a#fragment and splits at the first?; it doesn't useurlsplit(), which reads a route starting with//as a host. The undocumentedQueryString.urlattribute and__call__(page.query()) are gone; nothing in the repo used them.TemplateRouteand query stringsTemplateRoute.match()ran the template against the whole route, query string included:/books/42?tab=reviews/books/:idid == "42?tab=reviews"id == "42"/store?ref=ad/store/books/42?next=/books/43/books/:idid == "42"It now matches only the path, as the declarative
Routeralready does, and also ignores a fragment. The client buildspage.routefrom the full URI, so a deep link can carry a fragment. This also fixes the routing guide's ownTemplateRoute(page.route)example and thetrolliexample for routes with a query string.Docs
QueryStringreference page.page.queryhad a one-line entry and an unlinked type, soget(),to_dictandpathweren't documented anywhere.Tests
test_query_string.pyopens a realSessionthe way the client connects, then checks:page.queryfollowspage.routeinmain(), inon_route_changeand after later route changes;push_routeparameters come back decoded once.test_template_route.pycovers path-only matching.flet-1.1.0without this change, 13 fail; the 5 that pass guard the new path/query/fragment splitting./?name=Joe&q=dom%26dogsgave{}and aKeyErrorinmain()before the fix, and{'name': 'Joe', 'q': 'dom&dogs'}after it.There's no integration test.
FletTestAppalways starts the app on/, because Flutter's test binding forces the initial route, so opening the app on a route with a query string can't be reproduced there.Summary by Sourcery
Fix route query parsing and template matching so query strings and fragments are handled consistently across app startup and navigation.
Bug Fixes:
page.queryread and decode parameters directly from the current route, including on initial app launch, without double decoding or incorrect path handling.TemplateRoutematch route paths independently of query strings and fragments.Enhancements:
QueryStringURL and refresh API, while keeping query results synchronized withpage.route.Documentation:
QueryStringAPI documentation and document query-string handling and path-only template matching in the Navigation and Routing guide.Tests:
TemplateRoutematching with query strings and fragments and clearing parameters after failed matches.Chores: