TheEthicalBoy
Posted on December 19, 2022
Feel free to scroll down to the end of this article to look at the final result. :)
Project’s Dependencies
For this project, we will need just two python packages: Flet and Pyshorteners.
Flet will be the frontend person in charge of the building and rendering of the UI, while Pyshorteners will be the backend person in charge of shortening the given URLs/links.
From this, you can already understand that Flet could be combined with any Python library of your choice (pyshorteners, in our case).
Installing our Dependencies
Please make sure you have Python (preferably v3.7 or above) installed, then run these two commands in your terminal/command line:
pip install flet
pip install pyshorteners
I recommend you do this in a Virtual Machine (VM).
After the installations are done, create a new file and name it as you wish (ex: my-url-shortener) and run this basic “Hello, World!” code using your favorite IDE to ensure you are good to go.
import flet as ft
def main(page: ft.Page):
page.add(ft.Text(value="Hello, world!"))
ft.app(target=main)
Throughout this article, I will be importing Flet with the alias ft
, just like Numpy is commonly aliased np
or Pandas pd
.
The execution of that code block opens a native window containing the rendered output. Because we will deal with links, let’s render the output in our web browser. To do that, modify the last line of code, as shown below:
ft.app(target=main, view=ft.WEB_BROWSER) # add 'port' parameter to specify the port to be used
The User Interface (UI)
The UI for this project will be straightforward. We will need a text field to get the user input (URL/link), with a button to validate that input.
This input will be sent to the backend for processing, and the output will be displayed as text on the screen.
We will also have a button to copy the generated shortened links and another to open/view the link in a browser tab. Exciting, right?
Application’s Base
Let’s give our application a title and add an app bar.
import flet as ft
def main(page: ft.Page):
page.title = "URL Shortener" # title of application/page
page.horizontal_alignment = "center" # center our page's content (remove or change at wish)
page.appbar = ft.AppBar(
title=ft.Text("URL Shortener", color=ft.colors.WHITE), # title of the AppBar, with a white color
center_title=True, # we center the title
bgcolor=ft.colors.BLUE, # a color for the AppBar's background
)
page.add(ft.Text(value="Hello, world!")) # some placeholder content (nothing will be shown without this line)
ft.app(target=main, view=ft.WEB_BROWSER) # add 'port' parameter to specify the port to be used
After executing your program, you should see something similar to one of the images above.
‘One of the images’ because Flet uses your system’s theme by default. For consistency, let’s use the light theme. So, let’s explicitly set the theme_mode
.
#...
def main(page: ft.Page):
page.theme_mode = "light" # there are only 3 possible values: "dark", "light" and "system"
#...
I omit some code lines (using #…) to save some space.
Getting the User’s Input
I mentioned earlier that we will use a text field for this.
Let’s create one, store it in a variable named text_field
, and add it to our page/UI.
# ...
page.appbar = ft.AppBar(
# ...
)
text_field = ft.TextField(
value='https://github.com/ndonkoHenri', # a test link
label="Long URL", # the field's label
hint_text="type long url here", # the field's hint-text
max_length=200, # the maximum length of inputted links
keyboard_type="url", # the field's keyboard type
suffix=ft.FilledButton("Shorten!"), # a button in the field, to shorten the inputted links
)
page.add(
text_field,
ft.Text("Generated URLs:", weight="bold", size=23)
) # add our text field to the page/UI
# ...
After execution of your program now, you should see something similar to this:
Output Display
Before moving on, let’s import pyshorteners below Flet and initialize it.
import flet as ft
import pyshorteners # pip install pyshorteners
shortener = pyshorteners.Shortener() # create an instance (initialization)
# ...
Now, when shortening an entered long URL, we will display a Row
containing three main things: a shortened link, a copy button, and a button to open the shortened link in a browser tab.
This Row
will be displayed several times, so we need to create an isolated and reusable component. We will create a Python class and place it below the shortener
variable.
# ...
class ShortLinkRow(ft.Row):
# a row containing the shortened url, and two buttons ('copy', and 'open in browser')
def __init__(self, shortened_link, link_source):
"""
We create a new class called `ShortenedLinkRow` that inherits from `ft.Row`.
The constructor takes two arguments/parameters: `shortened_link` and `source`.
:param shortened_link: the shortened link
:param link_source: the service hosting the shortened_link
"""
super().__init__() # required when overwriting the constructor
self.tooltip = link_source # set the tooltip of the row itself to the link provider/source
self.alignment = "center" # center the contents of this row
# the controls/content of our Row
self.controls = [
ft.Text(value=shortened_link, size=16, selectable=True, italic=True),
ft.IconButton(
icon=ft.icons.COPY, # the icon to be showed
on_click=lambda e: self.copy(shortened_link), # when this button is clicked, call the `copy` method, passing the shortened link as parameter
bgcolor=ft.colors.BLUE_700,
tooltip="copy" # to be showed when hovering on this button
),
ft.IconButton(
icon=ft.icons.OPEN_IN_BROWSER_OUTLINED, # the icon to be showed
tooltip="open in browser", # to be showed when hovering on this button
on_click=lambda e: e.page.launch_url(shortened_link) # when this button is clicked, open a browser tab with that shortened link
)
]
def copy(self, value):
"""
It copies the given value to the clipboard, and opens a Snackbar to inform the user.
:param value: The value to be copied to the clipboard
"""
self.page.set_clipboard(value)
self.page.show_snack_bar(
ft.SnackBar(
ft.Text("Link copied to clipboard!"),
open=True
)
)
Having this done, we now need to listen to events in the Textfield so that we can show the outputs at the right moment.
We will listen to the click of the ‘Submit’ button and press the ‘Enter’ keyboard key when the Text field is in focus. When one of these events occurs, Flet will run a particular function named shorten
, which we will create in a while.
Make the modifications below to your text_field
variable:
text_field = ft.TextField(
# ...
suffix=ft.FilledButton("Shorten!", on_click=shorten), # the function to be called when this button will be clicked
on_submit=shorten # the function to be called once the user presses the Enter keyboard key to submit entry
)
Now let’s create the callback function, and add it to the main function.
# ...(below page.appbar assignment)
def shorten(e):
"""Grabs the URL in the textfield, and displays shortened versions of it."""
user_link = text_field.value # retrieve the content of the textfield
if user_link: # if the textfield is not empty
# if the entered text in the textfield is not a valid URl, the program may break, hence the need to catch that
try:
page.add(ft.Text(f"Long URL: {user_link}", italic=False, weight='bold'))
page.add(ShortLinkRow(shortened_link=shortener.tinyurl.short(user_link), link_source="By tinyurl.com"))
page.add(ShortLinkRow(shortened_link=shortener.chilpit.short(user_link), link_source="By chilp.it"))
page.add(ShortLinkRow(shortened_link=shortener.clckru.short(user_link), link_source="By clck.ru"))
page.add(ShortLinkRow(shortened_link=shortener.dagd.short(user_link), link_source="By da.dg"))
except Exception as exception: # the error might be that a url shortening service from pyshorteners failed to shorten our url
print(exception)
# inform the user that an error has occurred
page.show_snack_bar(
ft.SnackBar(
ft.Text("Sorry, but an error occurred. Please retry, or refresh the page."),
open=True
)
)
else: # if the textfield is empty (no text)
# inform the user
page.show_snack_bar(
ft.SnackBar(
ft.Text("Please enter a URL in the field!"),
open=True
)
)
# ...
If you got lost along the line, please check this gist for the complete code. Below is a capture of the final result:
I deployed an online version of this app here for you. Test it out and let me please have your impressions.
Note that you could eventually package this app as a standalone executable file or deploy it on the web. That’s just the cross-platform nature of Flet.
It’s Your Turn
To make this project better or more advanced, try this out:
- add the possibility to scroll the page vertically
- expose more URL shortening APIs from pyshorteners (I only exposed four in this article, but more than ten are available)
- change the fonts used in the application.
You can use this as a reference/solution if you get stuck. Please, let me know if you tried it or have any questions. I will be happy to help.
Thanks for reading!
Posted on December 19, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.