From 0fabbe6ac2352bd19a4a4d43cf4f153b122295e2 Mon Sep 17 00:00:00 2001 From: stu Date: Fri, 11 Aug 2023 22:56:20 +0800 Subject: [PATCH 1/5] routing: lazy route decorator --- client_code/routing/__init__.py | 2 +- client_code/routing/_decorators.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/client_code/routing/__init__.py b/client_code/routing/__init__.py index c85597f1..ac8f59f4 100644 --- a/client_code/routing/__init__.py +++ b/client_code/routing/__init__.py @@ -12,7 +12,7 @@ from . import _navigation from . import _router as _r from ._alert import alert -from ._decorators import error_form, redirect, route, template +from ._decorators import error_form, lazy_route, redirect, route, template from ._logging import logger from ._router import NavigationExit, launch from ._utils import ( diff --git a/client_code/routing/_decorators.py b/client_code/routing/_decorators.py index e2115be0..473b61a9 100644 --- a/client_code/routing/_decorators.py +++ b/client_code/routing/_decorators.py @@ -93,3 +93,19 @@ def error_form(cls): cls._route_props = {"title": None, "layout_props": {}} _router._error_form = cls return cls + + +def lazy_route( + url_pattern="", url_keys=[], title=None, full_width_row=False, template=None +): + route_wrapper = route(url_pattern, url_keys, title, full_width_row, template) + + def wrapper(fn): + class Lazy: + def __new__(cls, **properties): + form_class = fn() + return form_class.__new__(form_class, **properties) + + return route_wrapper(Lazy) + + return wrapper From 02c244f76811aaa6c0ca5986efdaacc985a70a72 Mon Sep 17 00:00:00 2001 From: stu Date: Fri, 11 Aug 2023 23:04:15 +0800 Subject: [PATCH 2/5] Add docs and fix the decorator --- client_code/routing/_decorators.py | 3 ++- docs/guides/modules/routing.rst | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/client_code/routing/_decorators.py b/client_code/routing/_decorators.py index 473b61a9..a05abb7e 100644 --- a/client_code/routing/_decorators.py +++ b/client_code/routing/_decorators.py @@ -106,6 +106,7 @@ def __new__(cls, **properties): form_class = fn() return form_class.__new__(form_class, **properties) - return route_wrapper(Lazy) + route_wrapper(Lazy) + return fn return wrapper diff --git a/docs/guides/modules/routing.rst b/docs/guides/modules/routing.rst index 656c888e..dc9074bf 100644 --- a/docs/guides/modules/routing.rst +++ b/docs/guides/modules/routing.rst @@ -389,6 +389,22 @@ Decorators If the ``before_unload`` method is added it will be called whenever the form currently in the ``content_panel`` is about to be removed. If any truthy value is returned then unloading will be prevented. See `Form Unloading <#form-unloading>`__. +.. function:: routing.lazy_route(url_pattern, url_keys=[], title=None, full_width_row=False, template=None) + + .. code:: python + + from anvil_extras import routing + + @routing.lazy_route('article', url_keys=['id', routing.ANY], title="Article-{id} | RoutingExample") + def article_route(): + from ..ArticleForm import ArticleForm + return ArticleForm + + This decorator allows you to lazyily load Forms. When using ``@routing.route`` all Forms that are routes must be imported before the app starts. + This is fine for most small applications, but as your application grows you may find that executing all the code for all the Forms is slow. + The ``lazy_route`` decorator should decorate a function that imports the Form and returns it. + + .. function:: routing.redirect(path, priority=0, condition=None) The redirect decorator can decorate a function that will intercept the current navigtation, depending on its ``path``, ``priority`` and ``condition`` arguments. From ec481dd35c0799f7ab9958c205463650ded50faa Mon Sep 17 00:00:00 2001 From: stu Date: Fri, 11 Aug 2023 23:08:36 +0800 Subject: [PATCH 3/5] Update change log --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25f463aa..5ab31b43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Unreleased +## New Features +* `routing.lazy_route` - allows you to lazily load Forms whilst using routing + https://github.com/anvilistas/anvil-extras/pull/442 + ## Bug Fixes * routing was no longer dismissing alerts on navigation you will now need to use `routing.alert` in place of `anvil.alert` for an alert to be dismissed on navigation From dfa0ad9be22f503d907098154afbdcbfbd7a5299 Mon Sep 17 00:00:00 2001 From: stu Date: Fri, 11 Aug 2023 23:18:59 +0800 Subject: [PATCH 4/5] Only call the lazy method once --- client_code/routing/_decorators.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client_code/routing/_decorators.py b/client_code/routing/_decorators.py index a05abb7e..ee305185 100644 --- a/client_code/routing/_decorators.py +++ b/client_code/routing/_decorators.py @@ -102,8 +102,12 @@ def lazy_route( def wrapper(fn): class Lazy: + _form = None + def __new__(cls, **properties): - form_class = fn() + form_class = cls._form + if form_class is None: + form_class = cls._form = fn() return form_class.__new__(form_class, **properties) route_wrapper(Lazy) From da5fcbb97a6636d30f7227ad0f03d8d08a287b09 Mon Sep 17 00:00:00 2001 From: stu Date: Fri, 11 Aug 2023 23:40:32 +0800 Subject: [PATCH 5/5] fix typo --- docs/guides/modules/routing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/modules/routing.rst b/docs/guides/modules/routing.rst index dc9074bf..fd33b64c 100644 --- a/docs/guides/modules/routing.rst +++ b/docs/guides/modules/routing.rst @@ -400,7 +400,7 @@ Decorators from ..ArticleForm import ArticleForm return ArticleForm - This decorator allows you to lazyily load Forms. When using ``@routing.route`` all Forms that are routes must be imported before the app starts. + This decorator allows you to lazily load Forms. When using ``@routing.route`` all Forms that are routes must be imported before the app starts. This is fine for most small applications, but as your application grows you may find that executing all the code for all the Forms is slow. The ``lazy_route`` decorator should decorate a function that imports the Form and returns it.