# 🔥Fast-Flet
`Fast-Flet` is a package built as a complement to `Flet`, designed for newbies which facilitates the handling of flet events, designed to work with numerous pages of your created application. It also provides a better MVC construction of your code, which can be scalable and easy to read. But it not only limits the MVC model but you can **adapt it according to your preferences**.
## 📌Flet events it handles
- `on_route_change` : Dynamic routing (automatic and manual)
- `on_view_pop`
- `on_keyboard_event`
- `on_resize`
- `on_error`
## 📌It also contains extra options:
- Responsive of the page in terms of its height. [view](#responsive)
- Login control of assigned pages. [view](#login)
- Async compatible. [view](#async)
- Automatic dynamic routing. [view](#route_automatic)
- Manual dynamic routing. [view](#route_manual)
- Compatible with `Flet_Fastapi`. [view](https://flet.dev/docs/guides/python/deploying-web-app/running-flet-with-fastapi)
- How to use `Fast-Flet`? [view](#use)
**class of `Fast-Flet`**
- Using `ViewPage` class. [view](#view_page)
- Using `MyController` class. [view](#my_controller)
- Using of `on_resize`. [view](#my_keyboard)
- Using of `on_keyboard_event`. [view](#my_page_resize)
## 💻Installation:
It is installed automatically:
* flet
* flet_fastapi
* uvicorn
```
pip install fast-flet
```
## 💻Update:
```
pip install fast-flet --upgrade
```
## ⌨️`Fast-Flet` Cli
Contains new quickstart commands that you can use in the terminal. They will allow you to start developing immediately and without any effort.
- Create the MVC based project
```
fast-flet init mvc
```
- Create the MVC based project (async)
```
fast-flet init mvc --async
```
- Create a custom project, only the `views` folder and the `app.py` file will be created.
```
fast-flet init app
```
- Create a custom project, only the `views` folder and the `app.py` file will be created. (async)
```
fast-flet init app --async
```
- Check the version
```
fast-flet version
```
<a name="use"></a>
## 🚀 HOW TO USE FAST-FLET?
`Fast-Flet` presents a main structure based on MVC and the other is according to how the user wants to adapt it.
### Suggested MVC
<img src="https://raw.githubusercontent.com/Jrxvx/fast-flet/master/media/mvc.png"/>
### Adaptive according to the user.
In this case it only requires the `app.py` file and the `views` folder, the rest is already customizable in terms of more folders or files.
<img src="https://raw.githubusercontent.com/Jrxvx/fast-flet/master/media/personalized.png"/>
## Fast-Flet app example:
We create the main file `app.py` in the root path of the project, which is where `Flet` will be initialized.
```python
import flet as ft
from fast_flet import RoutePage, ConfView
def main(page: ft.Page):
# CONFIGURACION GENERAL
theme = ft.Theme()
platforms = ["android", "ios", "macos", "linux", "windows"]
for platform in platforms: # Removing animation on route change.
setattr(theme.page_transitions, platform, ft.PageTransitionTheme.NONE)
page.theme = theme
# View flet configuration in all views
view = ConfView(
appbar=lambda: ft.AppBar(
title=ft.Text("fast-flet"),
center_title=False,
bgcolor=ft.colors.SURFACE_VARIANT,
actions=[
ft.IconButton(ft.icons.WB_SUNNY_OUTLINED),
ft.IconButton(ft.icons.FILTER_3),
ft.PopupMenuButton(
items=[
ft.PopupMenuItem(text="Item 1"),
ft.PopupMenuItem(
text="Checked item", checked=False
),
]
),
],
)
)
# ROUTING AND HANDLING VIEWS IN AUTOMATICO
fast_flet = RoutePage(
page=page,
route="/index",
route_login='/login',
route_404="/404-fast-flet",
view=view,
)
# WE RUN THE ROUTING OF THE VIEWS
fast_flet.run()
ft.app(main,
port=8000,
view=ft.AppView.WEB_BROWSER,
web_renderer=ft.WebRenderer.AUTO,
route_url_strategy='hash'
)
```
<a name="route_automatic"></a>
### Class usage `RoutePage`:
By default this `Fast-Flet` class performs automatic routing. It has the following attributes.
- `page:` 'page' parameter of the main function of the app or website (mandatory).
- `route:` Path where the app or website will be initialized (mandatory).
- `route_login:` Login route, where it will be redirected.
- `route_404:` Custom page path not found.
- `view:` General configuration of all the `'View'` of the page `'(page.views)'`
- `manual_routing:` Use manual routing of `'views'`
### Class usage `ConfView`:
Contains all [`View`](https://flet.dev/docs/controls/view) Flet properties to assign to all pages.
- Note: if the parameter receives a flet class, `lambda` is used. (Not in async)
Example:
```python
controls: list = None
appbar: AppBar = None # use lambda
floating_action_button: FloatingActionButton = None # use lambda
navigation_bar: NavigationBar = None # use lambda
vertical_alignment: MainAxisAlignment = None # use lambda
horizontal_alignment: CrossAxisAlignment = None # use lambda
spacing: int = None
padding: int = None # use lambda
bgcolor: str = None # use lambda
# ScrollableControl specific
scroll: ScrollMode = None # use lambda
auto_scroll: bool = None
fullscreen_dialog: bool = None
on_scroll_interval: OptionalNumber = None # use lambda
on_scroll = None
```
<a name="route_manual"></a>
## Manual dynamic routing.
To perform manual routing, it is required to use the `add_routes()` method from `RoutePage` and import `add_view()` from `Fast-Flet`.
🔎 **Note:** To use it you must first activate it in the `RoutePage` class with its attribute `manual_routing= True` (by default it is False).
### Example:
```python
import flet as ft
from fast_flet import RoutePage,add_view
# Import the View classes from the views folder to use in add_routes
from views.index import View
from views.task import View as Taskview
from views.contador import View as ContadorView
from views.login import View as LoginView
from views.resize import View as ResizeView
from views.page_404 import View as Page_404View
def main(page: ft.Page):
# CONFIGURACION GENERAL
theme = ft.Theme()
platforms = ["android", "ios", "macos", "linux", "windows"]
for platform in platforms: # Removing animation on route change.
setattr(theme.page_transitions, platform, ft.PageTransitionTheme.NONE)
page.theme = theme
fast_flet = RoutePage(
page=page,
route="/index",
route_login='/login',
route_404="/404-fast-flet",
manual_routing= True
)
# ROUTING AND MANAGEMENT VIEWS IN MANUAL'
fast_flet.add_routes(
[
add_view(url='/index',view=View()),
add_view(url='/task',view=Taskview(),clear=False),
add_view(url='/counter/:id/:name',view=ContadorView(), clear=False),
add_view(url='/login',view=LoginView()),
add_view(url='/resize',view=ResizeView(), clear=False),
add_view(url='/404-fast-flet',view=Page_404View(), clear=False),
]
)
# WE RUN THE ROUTING OF THE VIEWS
fast_flet.run()
ft.app(main,
port=8000,
view=ft.AppView.WEB_BROWSER,
web_renderer=ft.WebRenderer.AUTO,
route_url_strategy='hash'
)
```
### Using the `add_view()` function
The parameters that this function has are:
- `url` We set the url.
- `view` We use the class imported from the views folder.
- `clear` All views stored in `page.views` are removed (default is true).
### ⚡RoutePage `run()` method
`run()` Initialize Fast-Flet
<a name="async"></a>
## 🔀Async apps with Fast-Flet
To use Flet in async mode, it is initialized with the `run_async()` method of the `RoutePage` class
<a name="view_page"></a>
## 🗂️In the `views` folder a file is created for example `index.py`
🔎Note: When using automatic routing the class must be called `View` and inherit `ViewPage` from `Fast-Flet`.
```python
import flet as ft
from fast_flet import ViewPage
class View(ViewPage):
def __init__(self) -> None:
super().__init__()
self.call.route = '/index'
# remove icon return to previous view of 'appbar', if it is activated
self.call.page_clear = True # clean the list of views added to the page (default is false)
# View general configuration
def build(self):
# we assign a url
self.route = '/index'
page = self.call.page
page.title = 'Index'
# modify View properties : https://flet.dev/docs/controls/view
self.appbar.title = ft.Text('Home')
self.controls = [
ft.Column(
[
ft.Container(
content=ft.Column(
[
ft.FilledButton(
'go Counter',
on_click=lambda e: e.page.go(
'/counter/100/fast-flet')
),
ft.FilledButton(
'go Task',
on_click=lambda e:e.page.go('/task')
),
ft.FilledButton(
'go Resize',
on_click=lambda e:e.page.go('/resize')
),
],
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER
),
width=450,
height=450,
bgcolor='blue800',
alignment=ft.alignment.center,
border_radius=20
),
]
)
]
self.horizontal_alignment = ft.CrossAxisAlignment.CENTER
self.vertical_alignment = ft.MainAxisAlignment.CENTER
self.bgcolor = ft.colors.BLACK
```
## The `View` class inherits:
### `self.call`
- `self.call.page: Page` Receives the page from the main function.
- `self.call.route: str = '/'` Establish a route (Automatic Routing).
- `self.call.page_clear:bool = False` Set removal of list `page.views` stored by flet (Automatic Routing).
- `self.call.url_params: list = None` Receives the parameters sent through the url.
- `self.call.is_login: bool = False` Establish if the page requires login.
- `self.call.on_keyboard_event: Mykeyboard` Receive information about the event: `'on_keyboard_event'`.
- `self.call.on_resize: MyPageResize` Receive information about the event: `on_resize`.
### Configure flet View properties [`flet.View`](https://flet.dev/docs/controls/view), It is used in the `build()` method.
In the `build()` method that inherits from the `ViewPage` class, you can add new controllers and assign value of the page properties.
- `self.controls: list = None`
- `self.appbar: AppBar = None`
- `self.floating_action_button: FloatingActionButton = None`
- `self.navigation_bar: NavigationBar = None`
- `self.vertical_alignment: MainAxisAlignment = None`
- `self.horizontal_alignment: CrossAxisAlignment = None`
- `self.spacing: int = None`
- `self.padding: int = None`
- `self.bgcolor: str = None`
ScrollableControl specific
- `self.scroll: ScrollMode = None`
- `self.auto_scroll: bool = None`
- `self.fullscreen_dialog: bool = None`
- `self.on_scroll_interval: int = None`
- `self.on_scroll = None`
<a name="login"></a>
## 🔐How to configure page access protection? (login)
- To do this we use the `login_required()` method that inherits from the ViewPage class, the configuration will only be done once.
- We use `self.call.is_login = True` Requires login to access the page (previously configured)
```python
class View(ViewPage):
def __init__(self) -> None:
super().__init__()
self.call.route = '/login' # we assign a url
self.call.is_login = True # requires login to access the page (previously configured)
# required login configuration
def login_required(self) -> bool:
super().login_required()
class_login = Login() # import the login controller class
add_login_required = lambda:class_login.login() #We use the method of the class where the login configuration has been made
return add_login_required() # Returns login validation.
# View general configuration
def build(self):
self.call.page.title = 'Login'
.......
........
```
<a name="my_keyboard"></a>
## ⚙️Use `self.call.on_keyboard_event`
Once the `ViewPage` attributes are inherited we can use them.
🔎`self.call.on_keyboard_event` It has the following methods:
- `add_control('<controller method>')` Adds a controller configuration (controller method), which is executed with the `on_keyboard_event` event.
- `def key()` Returns the value entered by keyboard.
- `def shift()` Returns the value entered by keyboard.
- `def ctrl()` Returns the value entered by keyboard.
- `def alt()` Returns the value entered by keyboard.
- `def meta()` Returns the value entered by keyboard.
- `def test()` Returns a message of all the values entered by keyboard. (key, Shift, Control, Alt, Meta)
<a name="my_page_resize"></a>
## ⚙️ Use `self.call.on_resize`
🔎 `self.call.on_resize` It has the following methods:
- `controls` Stores the checklist to be responseve.
- `add_control('<control>', '<height>', '<max_height>')` Add a control that will be a response when executing the 'on_resize' event.
- ` add_controls = '<lambda>'` Stores an anonymous function.
- `response('<'controls>')` Configure the response of all controls.
- `add_def_control = <lambda>` Add a function that will be executed with the `on_resize` event, the function must be from the `controllers` folder.
### Example:
🗂️ In the `views` folder of the `task.py` file
```python
def build(self):
# ------
# We configure all the values of the page.
page = self.call.page # we get all the values of the page.
page.title = 'test'
# --------
on_resize = self.call.on_resize # on_resize values are obtained
on_keyboard = self.call.on_keyboard_event # the values of on_keyboard_event are obtained
task = ContentTask(on_resize, on_keyboard) # flet custom control
# modify View properties : https://flet.dev/docs/controls/view
self.appbar.title = ft.Text('Task')
self.controls = [
task
]
```
`Flet` custom control
```python
class ContentTask(ft.UserControl):
def __init__(self, on_resize: MyPageResize, on_keyboard: Mykeyboard):
super().__init__()
# We create an object of the controller class of this class, to be able to use its methods.
self.new_control = ContentTaskC(self, on_resize, on_keyboard)
self.on_keyboard = on_keyboard # the values of on_keyboard_event are obtained
# add a function to on_keyboard, which will be executed according to what is established in the function, it will be executed with keyboard input.
self.on_keyboard.add_control(self.new_control.add_on_keyboard)
self.on_resize = on_resize # on_resize values are obtained
self.new_control.user_control = Task # # We send the class that we are going to use in the controller of this class
self.input = ft.TextField(
col=8,
label='Enter the task',
multiline=True,
autocorrect=True,
helper_text="'Alt'+'L' -> to add task",
on_focus=self.new_control.update_input,
)
self.colum_task = ft.Column(scroll=ft.ScrollMode.ADAPTIVE)
self.response_page = ft.Container(
col={'sm': 5},
bgcolor=ft.colors.BLACK26,
height=self.on_resize.height - 80,
padding=10,
border_radius=10
)
self.response_task = ft.Container(
col={'sm': 11},
bgcolor=ft.colors.BLACK12,
height=self.on_resize.height-244,
padding=10,
border_radius=10,
)
# We add the controllers that are height responsive, if it is not displayed the page has to be reloaded (possible flet error)
self.on_resize.add_control(self.response_page, 80, 420)
self.on_resize.add_control(self.response_task, 244, 383)
self.on_resize.add_controls = lambda: self.new_control.response(
self.on_resize.controls) # we add all the controls
def build(self):
self.response_task.content = self.colum_task
self.response_page.content = ft.ResponsiveRow(
controls=[
ft.Text('Task', size=25,
text_align=ft.TextAlign.CENTER),
ft.ResponsiveRow(
controls=[
self.input,
ft.FilledButton(
'ADD',
col=4,
on_click=self.new_control.add_task
)
],
vertical_alignment=ft.CrossAxisAlignment.CENTER
),
self.response_task
],
alignment=ft.MainAxisAlignment.CENTER
)
return ft.ResponsiveRow(
controls=[
self.response_page
],
alignment=ft.MainAxisAlignment.CENTER,
)
```
<a name="my_controller"></a>
## 🗂️In the `controllers` folder of the task.py file
The Fast-Flet MyController class contains the following inheriting attributes.
- `self.call.model = None` It is assigned the class of the file.py in the models folder.
- `self.call.on_resize = on_resize` It is assigned the self.call.on_resize of the View class from the file.py in the views folder.
- `self.call.on_keyboard_event = on_keyboard` It is assigned the self.call.on_keyboard_event of the View class in the .py file in the views folder.
- `self.x = _self` The custom control object is stored.
- `self._user_control = None` The class that will be used in the custom control is stored.
```python
# view's ContentTask class handler
class ContentTaskC(MyController):
def __init__(self, _self: object, on_resize: MyPageResize = None, on_keyboard=None) -> None:
super().__init__(_self, on_resize, on_keyboard)
def _add_task(self):
if self.x.input.value != '':
input_task = self.x.input.value
task = self.user_control(self.delete, input_task, self.call.on_keyboard_event)
self.x.colum_task.controls.append(task)
self.x.input.value = ''
self.x.input.label = 'Enter a task'
else:
self.x.input.label = 'Enter a task please'
self.x.input.border_color=ft.colors.RED
self.x.update()
sleep(2)
self.x.input.border_color=None
self.x.update()
def add_task(self,e):
self._add_task()
def delete(self, task):
self.x.colum_task.controls.remove(task)
self.x.update()
def update_input(self,e):
self.x.input.border_color=None
self.x.update()
# used with keyboard input
def add_on_keyboard(self):
keyboard = self.call.on_keyboard_event
if keyboard.key() == 'L' and keyboard.alt():
self._add_task()
```
<a name="responsive"></a>
## 🔗Responsive of the page in terms of its height.
In the previous example you can see the responsible use of the page height.
```python
self.response_page = ft.Container(
col={'sm': 5},
bgcolor=ft.colors.BLACK26,
height=self.on_resize.height - 80,
padding=10,
border_radius=10
)
self.response_task = ft.Container(
col={'sm': 11},
bgcolor=ft.colors.BLACK12,
height=self.on_resize.height-244,
padding=10,
border_radius=10,
)
# We add the controllers that are height responsive, if it is not displayed the page has to be reloaded (possible flet error)
self.on_resize.add_control(self.response_page, 80, 420)
self.on_resize.add_control(self.response_task, 244, 383)
self.on_resize.add_controls = lambda: self.new_control.response(
self.on_resize.controls) # we add all the controls
```
## 🔗 Links
[![github](https://img.shields.io/badge/my_portfolio-000?style=for-the-badge&logo=github&logoColor=white)](https://github.com/Jrxvx)[![pypi](https://img.shields.io/badge/Pypi-0A66C2?style=for-the-badge&logo=pypi&logoColor=white)](https://pypi.org/project/fast-flet)
## 🔋Sample applications with Fast-Flet
- **[`threading`](https://github.com/Jrxvx/fast-flet/tree/master/test)** (defect `Flet`)
- **[`Async`](https://github.com/Jrxvx/fast-flet/tree/master/test/async)** (with `flet_fastapi`) [watch online](https://jrxvx-tools-fastflet.hf.space)
## License
[Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/)
Raw data
{
"_id": null,
"home_page": "https://github.com/Jrxvx/Fast-Flet",
"name": "fast-flet",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": "",
"keywords": "python web template,flet,app python,flet mvc,fast flet mvc,fast flet,flet-fastapi,flutter python,flet personalized,web application,development",
"author": "Jrxvx",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/38/6f/8ee58c905d690d5c8ca2aa4c71c592e3a27a0f11741a2e65bdce7c0648c4/fast-flet-0.1.1.tar.gz",
"platform": null,
"description": "\r\n# \ud83d\udd25Fast-Flet\r\n`Fast-Flet` is a package built as a complement to `Flet`, designed for newbies which facilitates the handling of flet events, designed to work with numerous pages of your created application. It also provides a better MVC construction of your code, which can be scalable and easy to read. But it not only limits the MVC model but you can **adapt it according to your preferences**.\r\n\r\n\r\n## \ud83d\udcccFlet events it handles\r\n\r\n- `on_route_change` : Dynamic routing (automatic and manual)\r\n- `on_view_pop`\r\n- `on_keyboard_event`\r\n- `on_resize`\r\n- `on_error`\r\n\r\n## \ud83d\udcccIt also contains extra options:\r\n- Responsive of the page in terms of its height. [view](#responsive)\r\n- Login control of assigned pages. [view](#login)\r\n- Async compatible. [view](#async)\r\n- Automatic dynamic routing. [view](#route_automatic)\r\n- Manual dynamic routing. [view](#route_manual)\r\n- Compatible with `Flet_Fastapi`. [view](https://flet.dev/docs/guides/python/deploying-web-app/running-flet-with-fastapi)\r\n- How to use `Fast-Flet`? [view](#use)\r\n\r\n**class of `Fast-Flet`**\r\n- Using `ViewPage` class. [view](#view_page)\r\n- Using `MyController` class. [view](#my_controller)\r\n- Using of `on_resize`. [view](#my_keyboard)\r\n- Using of `on_keyboard_event`. [view](#my_page_resize)\r\n\r\n\r\n## \ud83d\udcbbInstallation:\r\nIt is installed automatically:\r\n* flet\r\n* flet_fastapi\r\n* uvicorn\r\n```\r\n pip install fast-flet\r\n```\r\n\r\n## \ud83d\udcbbUpdate:\r\n```\r\n pip install fast-flet --upgrade\r\n```\r\n\r\n## \u2328\ufe0f`Fast-Flet` Cli\r\nContains new quickstart commands that you can use in the terminal. They will allow you to start developing immediately and without any effort.\r\n\r\n- Create the MVC based project\r\n```\r\nfast-flet init mvc\r\n```\r\n- Create the MVC based project (async)\r\n```\r\nfast-flet init mvc --async\r\n```\r\n- Create a custom project, only the `views` folder and the `app.py` file will be created.\r\n```\r\nfast-flet init app\r\n```\r\n- Create a custom project, only the `views` folder and the `app.py` file will be created. (async)\r\n```\r\nfast-flet init app --async\r\n```\r\n- Check the version\r\n```\r\nfast-flet version\r\n```\r\n<a name=\"use\"></a>\r\n## \ud83d\ude80 HOW TO USE FAST-FLET?\r\n`Fast-Flet` presents a main structure based on MVC and the other is according to how the user wants to adapt it.\r\n\r\n### Suggested MVC\r\n\r\n<img src=\"https://raw.githubusercontent.com/Jrxvx/fast-flet/master/media/mvc.png\"/>\r\n\r\n### Adaptive according to the user.\r\nIn this case it only requires the `app.py` file and the `views` folder, the rest is already customizable in terms of more folders or files.\r\n\r\n<img src=\"https://raw.githubusercontent.com/Jrxvx/fast-flet/master/media/personalized.png\"/>\r\n\r\n\r\n## Fast-Flet app example:\r\n\r\nWe create the main file `app.py` in the root path of the project, which is where `Flet` will be initialized.\r\n\r\n```python\r\nimport flet as ft\r\nfrom fast_flet import RoutePage, ConfView\r\n\r\ndef main(page: ft.Page):\r\n # CONFIGURACION GENERAL\r\n theme = ft.Theme()\r\n platforms = [\"android\", \"ios\", \"macos\", \"linux\", \"windows\"]\r\n for platform in platforms: # Removing animation on route change.\r\n setattr(theme.page_transitions, platform, ft.PageTransitionTheme.NONE)\r\n\r\n page.theme = theme\r\n \r\n # View flet configuration in all views\r\n view = ConfView(\r\n appbar=lambda: ft.AppBar(\r\n title=ft.Text(\"fast-flet\"),\r\n center_title=False,\r\n bgcolor=ft.colors.SURFACE_VARIANT,\r\n actions=[\r\n ft.IconButton(ft.icons.WB_SUNNY_OUTLINED),\r\n ft.IconButton(ft.icons.FILTER_3),\r\n ft.PopupMenuButton(\r\n items=[\r\n ft.PopupMenuItem(text=\"Item 1\"),\r\n ft.PopupMenuItem(\r\n text=\"Checked item\", checked=False\r\n ),\r\n ]\r\n ),\r\n ],\r\n )\r\n )\r\n\r\n # ROUTING AND HANDLING VIEWS IN AUTOMATICO\r\n fast_flet = RoutePage(\r\n page=page,\r\n route=\"/index\",\r\n route_login='/login',\r\n route_404=\"/404-fast-flet\",\r\n view=view,\r\n )\r\n # WE RUN THE ROUTING OF THE VIEWS\r\n fast_flet.run()\r\n\r\n\r\nft.app(main,\r\n port=8000,\r\n view=ft.AppView.WEB_BROWSER,\r\n web_renderer=ft.WebRenderer.AUTO,\r\n route_url_strategy='hash'\r\n ) \r\n```\r\n<a name=\"route_automatic\"></a>\r\n### Class usage `RoutePage`:\r\nBy default this `Fast-Flet` class performs automatic routing. It has the following attributes.\r\n\r\n- `page:` 'page' parameter of the main function of the app or website (mandatory).\r\n\r\n- `route:` Path where the app or website will be initialized (mandatory).\r\n\r\n- `route_login:` Login route, where it will be redirected.\r\n\r\n- `route_404:` Custom page path not found.\r\n\r\n- `view:` General configuration of all the `'View'` of the page `'(page.views)'`\r\n\r\n- `manual_routing:` Use manual routing of `'views'`\r\n\r\n\r\n### Class usage `ConfView`:\r\nContains all [`View`](https://flet.dev/docs/controls/view) Flet properties to assign to all pages.\r\n\r\n- Note: if the parameter receives a flet class, `lambda` is used. (Not in async)\r\n\r\n Example:\r\n```python\r\n controls: list = None\r\n appbar: AppBar = None # use lambda\r\n floating_action_button: FloatingActionButton = None # use lambda\r\n navigation_bar: NavigationBar = None # use lambda\r\n vertical_alignment: MainAxisAlignment = None # use lambda\r\n horizontal_alignment: CrossAxisAlignment = None # use lambda\r\n spacing: int = None\r\n padding: int = None # use lambda\r\n bgcolor: str = None # use lambda\r\n \r\n # ScrollableControl specific\r\n scroll: ScrollMode = None # use lambda\r\n auto_scroll: bool = None\r\n fullscreen_dialog: bool = None\r\n on_scroll_interval: OptionalNumber = None # use lambda\r\n on_scroll = None\r\n```\r\n<a name=\"route_manual\"></a>\r\n## Manual dynamic routing.\r\nTo perform manual routing, it is required to use the `add_routes()` method from `RoutePage` and import `add_view()` from `Fast-Flet`.\r\n\r\n\ud83d\udd0e **Note:** To use it you must first activate it in the `RoutePage` class with its attribute `manual_routing= True` (by default it is False).\r\n\r\n### Example:\r\n```python\r\nimport flet as ft\r\nfrom fast_flet import RoutePage,add_view\r\n\r\n# Import the View classes from the views folder to use in add_routes\r\nfrom views.index import View\r\nfrom views.task import View as Taskview\r\nfrom views.contador import View as ContadorView\r\nfrom views.login import View as LoginView\r\nfrom views.resize import View as ResizeView\r\nfrom views.page_404 import View as Page_404View\r\n\r\ndef main(page: ft.Page):\r\n # CONFIGURACION GENERAL\r\n theme = ft.Theme()\r\n platforms = [\"android\", \"ios\", \"macos\", \"linux\", \"windows\"]\r\n for platform in platforms: # Removing animation on route change.\r\n setattr(theme.page_transitions, platform, ft.PageTransitionTheme.NONE)\r\n\r\n page.theme = theme\r\n \r\n fast_flet = RoutePage(\r\n page=page,\r\n route=\"/index\",\r\n route_login='/login',\r\n route_404=\"/404-fast-flet\",\r\n manual_routing= True\r\n )\r\n\r\n # ROUTING AND MANAGEMENT VIEWS IN MANUAL'\r\n fast_flet.add_routes(\r\n [\r\n add_view(url='/index',view=View()),\r\n add_view(url='/task',view=Taskview(),clear=False),\r\n add_view(url='/counter/:id/:name',view=ContadorView(), clear=False),\r\n add_view(url='/login',view=LoginView()),\r\n add_view(url='/resize',view=ResizeView(), clear=False),\r\n add_view(url='/404-fast-flet',view=Page_404View(), clear=False),\r\n ]\r\n )\r\n\r\n # WE RUN THE ROUTING OF THE VIEWS\r\n fast_flet.run()\r\n\r\n\r\nft.app(main,\r\n port=8000,\r\n view=ft.AppView.WEB_BROWSER,\r\n web_renderer=ft.WebRenderer.AUTO,\r\n route_url_strategy='hash'\r\n )\r\n```\r\n\r\n### Using the `add_view()` function\r\nThe parameters that this function has are:\r\n\r\n- `url` We set the url.\r\n- `view` We use the class imported from the views folder.\r\n- `clear` All views stored in `page.views` are removed (default is true).\r\n\r\n\r\n\r\n\r\n### \u26a1RoutePage `run()` method\r\n`run()` Initialize Fast-Flet\r\n\r\n<a name=\"async\"></a>\r\n## \ud83d\udd00Async apps with Fast-Flet\r\nTo use Flet in async mode, it is initialized with the `run_async()` method of the `RoutePage` class\r\n\r\n\r\n\r\n\r\n<a name=\"view_page\"></a>\r\n## \ud83d\uddc2\ufe0fIn the `views` folder a file is created for example `index.py`\r\n\r\n\ud83d\udd0eNote: When using automatic routing the class must be called `View` and inherit `ViewPage` from `Fast-Flet`.\r\n\r\n```python\r\nimport flet as ft\r\nfrom fast_flet import ViewPage\r\n\r\n\r\nclass View(ViewPage):\r\n def __init__(self) -> None:\r\n super().__init__()\r\n self.call.route = '/index'\r\n # remove icon return to previous view of 'appbar', if it is activated\r\n self.call.page_clear = True # clean the list of views added to the page (default is false)\r\n\r\n # View general configuration\r\n def build(self):\r\n # we assign a url\r\n self.route = '/index'\r\n page = self.call.page\r\n page.title = 'Index'\r\n\r\n # modify View properties : https://flet.dev/docs/controls/view\r\n self.appbar.title = ft.Text('Home')\r\n self.controls = [\r\n ft.Column(\r\n [\r\n ft.Container(\r\n content=ft.Column(\r\n [\r\n ft.FilledButton(\r\n 'go Counter',\r\n on_click=lambda e: e.page.go(\r\n '/counter/100/fast-flet')\r\n ),\r\n ft.FilledButton(\r\n 'go Task',\r\n on_click=lambda e:e.page.go('/task')\r\n ),\r\n ft.FilledButton(\r\n 'go Resize',\r\n on_click=lambda e:e.page.go('/resize')\r\n ),\r\n ],\r\n alignment=ft.MainAxisAlignment.CENTER,\r\n horizontal_alignment=ft.CrossAxisAlignment.CENTER\r\n ),\r\n width=450,\r\n height=450,\r\n bgcolor='blue800',\r\n alignment=ft.alignment.center,\r\n border_radius=20\r\n\r\n ),\r\n\r\n ]\r\n )\r\n ]\r\n\r\n self.horizontal_alignment = ft.CrossAxisAlignment.CENTER\r\n self.vertical_alignment = ft.MainAxisAlignment.CENTER\r\n self.bgcolor = ft.colors.BLACK\r\n\r\n```\r\n\r\n## The `View` class inherits:\r\n\r\n### `self.call`\r\n\r\n- `self.call.page: Page` Receives the page from the main function.\r\n\r\n- `self.call.route: str = '/'` Establish a route (Automatic Routing).\r\n\r\n- `self.call.page_clear:bool = False` Set removal of list `page.views` stored by flet (Automatic Routing).\r\n\r\n- `self.call.url_params: list = None` Receives the parameters sent through the url.\r\n\r\n- `self.call.is_login: bool = False` Establish if the page requires login.\r\n\r\n- `self.call.on_keyboard_event: Mykeyboard` Receive information about the event: `'on_keyboard_event'`.\r\n\r\n- `self.call.on_resize: MyPageResize` Receive information about the event: `on_resize`.\r\n\r\n### Configure flet View properties [`flet.View`](https://flet.dev/docs/controls/view), It is used in the `build()` method.\r\n\r\nIn the `build()` method that inherits from the `ViewPage` class, you can add new controllers and assign value of the page properties.\r\n\r\n- `self.controls: list = None`\r\n- `self.appbar: AppBar = None`\r\n- `self.floating_action_button: FloatingActionButton = None`\r\n- `self.navigation_bar: NavigationBar = None`\r\n- `self.vertical_alignment: MainAxisAlignment = None`\r\n- `self.horizontal_alignment: CrossAxisAlignment = None`\r\n- `self.spacing: int = None`\r\n- `self.padding: int = None`\r\n- `self.bgcolor: str = None`\r\n\r\nScrollableControl specific\r\n- `self.scroll: ScrollMode = None`\r\n- `self.auto_scroll: bool = None`\r\n- `self.fullscreen_dialog: bool = None`\r\n- `self.on_scroll_interval: int = None`\r\n- `self.on_scroll = None`\r\n\r\n<a name=\"login\"></a>\r\n## \ud83d\udd10How to configure page access protection? (login) \r\n\r\n- To do this we use the `login_required()` method that inherits from the ViewPage class, the configuration will only be done once.\r\n- We use `self.call.is_login = True` Requires login to access the page (previously configured)\r\n\r\n```python\r\nclass View(ViewPage):\r\n def __init__(self) -> None:\r\n super().__init__()\r\n self.call.route = '/login' # we assign a url\r\n self.call.is_login = True # requires login to access the page (previously configured)\r\n\r\n # required login configuration\r\n def login_required(self) -> bool:\r\n super().login_required()\r\n class_login = Login() # import the login controller class\r\n add_login_required = lambda:class_login.login() #We use the method of the class where the login configuration has been made\r\n return add_login_required() # Returns login validation.\r\n \r\n # View general configuration\r\n def build(self):\r\n self.call.page.title = 'Login'\r\n .......\r\n ........\r\n```\r\n\r\n\r\n\r\n<a name=\"my_keyboard\"></a>\r\n## \u2699\ufe0fUse `self.call.on_keyboard_event`\r\nOnce the `ViewPage` attributes are inherited we can use them.\r\n\r\n\ud83d\udd0e`self.call.on_keyboard_event` It has the following methods:\r\n\r\n- `add_control('<controller method>')` Adds a controller configuration (controller method), which is executed with the `on_keyboard_event` event.\r\n\r\n- `def key()` Returns the value entered by keyboard.\r\n- `def shift()` Returns the value entered by keyboard.\r\n- `def ctrl()` Returns the value entered by keyboard.\r\n- `def alt()` Returns the value entered by keyboard.\r\n- `def meta()` Returns the value entered by keyboard.\r\n- `def test()` Returns a message of all the values \u200b\u200bentered by keyboard. (key, Shift, Control, Alt, Meta)\r\n\r\n<a name=\"my_page_resize\"></a>\r\n## \u2699\ufe0f Use `self.call.on_resize`\r\n\ud83d\udd0e `self.call.on_resize` It has the following methods:\r\n\r\n- `controls` Stores the checklist to be responseve.\r\n- `add_control('<control>', '<height>', '<max_height>')` Add a control that will be a response when executing the 'on_resize' event.\r\n- ` add_controls = '<lambda>'` Stores an anonymous function.\r\n- `response('<'controls>')` Configure the response of all controls.\r\n\r\n- `add_def_control = <lambda>` Add a function that will be executed with the `on_resize` event, the function must be from the `controllers` folder.\r\n\r\n\r\n### Example:\r\n\r\n\ud83d\uddc2\ufe0f In the `views` folder of the `task.py` file\r\n```python\r\ndef build(self):\r\n\r\n # ------\r\n # We configure all the values \u200b\u200bof the page.\r\n page = self.call.page # we get all the values \u200b\u200bof the page.\r\n page.title = 'test'\r\n # --------\r\n\r\n on_resize = self.call.on_resize # on_resize values \u200b\u200bare obtained\r\n on_keyboard = self.call.on_keyboard_event # the values \u200b\u200bof on_keyboard_event are obtained\r\n task = ContentTask(on_resize, on_keyboard) # flet custom control\r\n\r\n # modify View properties : https://flet.dev/docs/controls/view\r\n self.appbar.title = ft.Text('Task')\r\n\r\n self.controls = [\r\n task\r\n ]\r\n```\r\n\r\n\r\n`Flet` custom control\r\n```python\r\nclass ContentTask(ft.UserControl):\r\n def __init__(self, on_resize: MyPageResize, on_keyboard: Mykeyboard):\r\n super().__init__()\r\n # We create an object of the controller class of this class, to be able to use its methods.\r\n self.new_control = ContentTaskC(self, on_resize, on_keyboard)\r\n self.on_keyboard = on_keyboard # the values \u200b\u200bof on_keyboard_event are obtained\r\n # add a function to on_keyboard, which will be executed according to what is established in the function, it will be executed with keyboard input.\r\n self.on_keyboard.add_control(self.new_control.add_on_keyboard)\r\n self.on_resize = on_resize # on_resize values \u200b\u200bare obtained\r\n self.new_control.user_control = Task # # We send the class that we are going to use in the controller of this class\r\n \r\n self.input = ft.TextField(\r\n col=8,\r\n label='Enter the task',\r\n multiline=True,\r\n autocorrect=True,\r\n helper_text=\"'Alt'+'L' -> to add task\",\r\n on_focus=self.new_control.update_input,\r\n\r\n )\r\n self.colum_task = ft.Column(scroll=ft.ScrollMode.ADAPTIVE)\r\n\r\n self.response_page = ft.Container(\r\n col={'sm': 5},\r\n bgcolor=ft.colors.BLACK26,\r\n height=self.on_resize.height - 80,\r\n padding=10,\r\n border_radius=10\r\n )\r\n\r\n self.response_task = ft.Container(\r\n col={'sm': 11},\r\n bgcolor=ft.colors.BLACK12,\r\n height=self.on_resize.height-244,\r\n padding=10,\r\n border_radius=10,\r\n\r\n )\r\n\r\n # We add the controllers that are height responsive, if it is not displayed the page has to be reloaded (possible flet error)\r\n self.on_resize.add_control(self.response_page, 80, 420)\r\n self.on_resize.add_control(self.response_task, 244, 383)\r\n self.on_resize.add_controls = lambda: self.new_control.response(\r\n self.on_resize.controls) # we add all the controls\r\n\r\n def build(self):\r\n self.response_task.content = self.colum_task\r\n self.response_page.content = ft.ResponsiveRow(\r\n controls=[\r\n ft.Text('Task', size=25,\r\n text_align=ft.TextAlign.CENTER),\r\n ft.ResponsiveRow(\r\n controls=[\r\n self.input,\r\n ft.FilledButton(\r\n 'ADD',\r\n col=4,\r\n on_click=self.new_control.add_task\r\n )\r\n ],\r\n vertical_alignment=ft.CrossAxisAlignment.CENTER\r\n ),\r\n self.response_task\r\n ],\r\n alignment=ft.MainAxisAlignment.CENTER\r\n )\r\n return ft.ResponsiveRow(\r\n controls=[\r\n self.response_page\r\n ],\r\n alignment=ft.MainAxisAlignment.CENTER,\r\n )\r\n```\r\n\r\n\r\n<a name=\"my_controller\"></a>\r\n## \ud83d\uddc2\ufe0fIn the `controllers` folder of the task.py file\r\n\r\nThe Fast-Flet MyController class contains the following inheriting attributes.\r\n\r\n- `self.call.model = None` It is assigned the class of the file.py in the models folder.\r\n- `self.call.on_resize = on_resize` It is assigned the self.call.on_resize of the View class from the file.py in the views folder.\r\n- `self.call.on_keyboard_event = on_keyboard` It is assigned the self.call.on_keyboard_event of the View class in the .py file in the views folder.\r\n- `self.x = _self` The custom control object is stored.\r\n- `self._user_control = None` The class that will be used in the custom control is stored.\r\n\r\n```python\r\n# view's ContentTask class handler\r\nclass ContentTaskC(MyController):\r\n def __init__(self, _self: object, on_resize: MyPageResize = None, on_keyboard=None) -> None:\r\n super().__init__(_self, on_resize, on_keyboard)\r\n \r\n def _add_task(self):\r\n if self.x.input.value != '':\r\n input_task = self.x.input.value\r\n task = self.user_control(self.delete, input_task, self.call.on_keyboard_event)\r\n self.x.colum_task.controls.append(task)\r\n self.x.input.value = ''\r\n self.x.input.label = 'Enter a task'\r\n else:\r\n self.x.input.label = 'Enter a task please'\r\n self.x.input.border_color=ft.colors.RED\r\n self.x.update()\r\n sleep(2)\r\n self.x.input.border_color=None\r\n self.x.update()\r\n\r\n def add_task(self,e):\r\n self._add_task()\r\n\r\n def delete(self, task):\r\n self.x.colum_task.controls.remove(task)\r\n self.x.update()\r\n \r\n def update_input(self,e):\r\n self.x.input.border_color=None\r\n self.x.update()\r\n \r\n # used with keyboard input\r\n def add_on_keyboard(self):\r\n keyboard = self.call.on_keyboard_event\r\n if keyboard.key() == 'L' and keyboard.alt():\r\n self._add_task()\r\n```\r\n<a name=\"responsive\"></a>\r\n## \ud83d\udd17Responsive of the page in terms of its height.\r\nIn the previous example you can see the responsible use of the page height.\r\n\r\n```python\r\nself.response_page = ft.Container(\r\n col={'sm': 5},\r\n bgcolor=ft.colors.BLACK26,\r\n height=self.on_resize.height - 80,\r\n padding=10,\r\n border_radius=10\r\n )\r\n\r\n self.response_task = ft.Container(\r\n col={'sm': 11},\r\n bgcolor=ft.colors.BLACK12,\r\n height=self.on_resize.height-244,\r\n padding=10,\r\n border_radius=10,\r\n\r\n )\r\n\r\n # We add the controllers that are height responsive, if it is not displayed the page has to be reloaded (possible flet error)\r\n self.on_resize.add_control(self.response_page, 80, 420)\r\n self.on_resize.add_control(self.response_task, 244, 383)\r\n self.on_resize.add_controls = lambda: self.new_control.response(\r\n self.on_resize.controls) # we add all the controls\r\n```\r\n\r\n## \ud83d\udd17 Links\r\n[![github](https://img.shields.io/badge/my_portfolio-000?style=for-the-badge&logo=github&logoColor=white)](https://github.com/Jrxvx)[![pypi](https://img.shields.io/badge/Pypi-0A66C2?style=for-the-badge&logo=pypi&logoColor=white)](https://pypi.org/project/fast-flet)\r\n\r\n## \ud83d\udd0bSample applications with Fast-Flet\r\n- **[`threading`](https://github.com/Jrxvx/fast-flet/tree/master/test)** (defect `Flet`)\r\n- **[`Async`](https://github.com/Jrxvx/fast-flet/tree/master/test/async)** (with `flet_fastapi`) [watch online](https://jrxvx-tools-fastflet.hf.space)\r\n\r\n## License\r\n\r\n[Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/)\r\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "\ud83d\udd25 Fast-Flet is a package built as a complement to Flet, designed for newbies which facilitates the handling of flet events, designed to work with numerous pages and be customizable.",
"version": "0.1.1",
"project_urls": {
"Bug Tracker": "https://github.com/Jrxvx/Fast-Flet/issues",
"Download": "https://github.com/Jrxvx/Fast-Flet",
"Homepage": "https://github.com/Jrxvx/Fast-Flet"
},
"split_keywords": [
"python web template",
"flet",
"app python",
"flet mvc",
"fast flet mvc",
"fast flet",
"flet-fastapi",
"flutter python",
"flet personalized",
"web application",
"development"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f78346d0f90e9a35a5361795420cbd309de2905890359e39149671a214647d8d",
"md5": "c120a18d03fe4a120870c48ad4beea2e",
"sha256": "9586f94add06d3e4316e899f2cf7f8d9354e4c1316d652dadc2cf7f1765b7c32"
},
"downloads": -1,
"filename": "fast_flet-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c120a18d03fe4a120870c48ad4beea2e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 3010202,
"upload_time": "2023-09-23T22:07:43",
"upload_time_iso_8601": "2023-09-23T22:07:43.462695Z",
"url": "https://files.pythonhosted.org/packages/f7/83/46d0f90e9a35a5361795420cbd309de2905890359e39149671a214647d8d/fast_flet-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "386f8ee58c905d690d5c8ca2aa4c71c592e3a27a0f11741a2e65bdce7c0648c4",
"md5": "76a4eb38dde1b859bbf618bc6fc298fb",
"sha256": "c55d19253c97f71a8e5a9a11ec01300b7321d1d9053cc784968a695285f517b9"
},
"downloads": -1,
"filename": "fast-flet-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "76a4eb38dde1b859bbf618bc6fc298fb",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 3009571,
"upload_time": "2023-09-23T22:07:45",
"upload_time_iso_8601": "2023-09-23T22:07:45.738924Z",
"url": "https://files.pythonhosted.org/packages/38/6f/8ee58c905d690d5c8ca2aa4c71c592e3a27a0f11741a2e65bdce7c0648c4/fast-flet-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-09-23 22:07:45",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Jrxvx",
"github_project": "Fast-Flet",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "fast-flet"
}