Building a task management app with Anvil
Anvil is a powerful and versatile tool for building full-stack web applications. With Anvil, you can quickly and easily create your UI and write Python code to control the front-end and back-end of your app. Creating apps with Anvil is fast and flexible, making it well-suited for building internal tools. This simple but powerful task management app demonstrates some of what you can do with Anvil.
I built the app’s UI with Anvil’s drag-and-drop editor and by writing front-end Python code. The back-end is also written in Python code in a secure Server Module. The app also uses Anvil’s built-in database system and user management service. Keep reading to learn more about how I built the task manager app with Python and Anvil.
What it does
The app is a simple task manager that allows you to create and manage projects. Each project is a configurable table of tasks where users can give tasks a priority level, add checkboxes and assign other users to tasks. The table of tasks is displayed using a Data Grid. Users can click on the cells in the table to edit their contents.
On the main page, there is a board view of all the projects. Here, you can add comments to or delete projects.
How it’s built
Building the database
Every Anvil app comes with a built-in database system built on top of PostgreSQL. Anvil’s Data Tables have a GUI for creating, editing and deleting tables, but tables can also be edited via Python code. To build my task manager app, I first needed to define my database schema.
I needed a way to store the columns in each user-created project table and the data in each row. I did this by first creating a table to store the name and type of all the columns in the projects.
Next, I created a table to store all the projects. This table has a column for the project name and a column that links to columns table. This connects each row in the Columns Data Table with its corresponding project.
Finally, a third Data Table stores the data for each row in all the projects. This table has a column linking back to Projects Data Table and a column for the row data, stored in a simple dictionary.
Writing back-end Python
Anvil’s Server Modules are a full server-side Python environment. Server Modules cannot be edited or seen by the user, so we can trust them to do what we tell them. By default, the Data Tables in an Anvil app are not editable by users, but they can be accessed from a Server Module. In the task manager app, any updates to the Data Tables occur in server-side functions within a Server Module. These functions can be called from client-side Forms using just one line of code.
For example, when a new column is added to a Data Grid, a new row is added to the Columns Data Table and that new row is then linked to the project in the Projects Data Table.
@anvil.server.callable def add_column_to_db(column_name, project, type): #project is a row from the Projects Data Table #add a new row to the Columns Data Table column_row = app_tables.columns.add_row(title=column_name, type=type) #link the new column to Projects project['columns'] += [column_row] return column_row
@anvil.server.callable decorator means that this function can easily be called from client-side code:
anvil.server.call('add_column_to_db', title, self.project, type)
Creating the UI with client-side Python
I created the app’s UI by using both Anvil’s drag-and-drop UI builder and by writing Python code to dynamically generate UI elements. For example, to create the project view page of my app, I dragged a Data Grid onto the page which is then used to display the table of tasks for each project:
The drag-and-drop designer makes building the front-end of your app a breeze, but sometimes you’ll want to build the front-end in code instead. For example, in the left navigation menu of my task management app, there are Links to all the projects in the app.
These Links are dynamically generated via code and updated anytime a project is created, deleted or renamed. Below is the Python function that searches the database for projects and creates Links for each project. The function is written in a client-side Form that runs in the user’s browser.
def add_project_links(self): #clear out the container that the links are in self.link_panel.clear() #get a list of the projects from the database for row in anvil.server.call('get_projects'): #create a link link = Link(text=row["project_name"], tag=row) #set up a event handler that opens the project when the link is clicked link.set_event_handler("click", self.open_project) #add the link to the container self.link_panel.add_component(link)
Anvil has many pre-built components that you can add to your apps, but you can also create your own component types using Custom Components. In my task manager app, I created a Custom Component that allows users to edit the text of the component by clicking on it. I reused this Custom Component throughout the app to make the contents of the project tables and the name of the projects user-editable.
Adding the User Management Service
Anvil also provides built-in user management that handles signup, login and user permissions. I added the Users service to my task management app so that team members can log in and work on projects together. Adding the Users service to an Anvil app automatically creates a Users table where you can manage access to your app. Since the Users table is an ordinary Data Table, I also used it to create a component for assigning tasks to users.
Anvil handles the login process, including single-sign-on with Google, Microsoft or your corporate SAML provider. I just needed to add
anvil.users.login_with_form() to my app so that users are presented with a login form on startup.
Clone the app to check out the source code and try it for yourself!
If you’re new to Anvil, why not try a 5-minute tutorial to learn more about building web apps with nothing but Python? Or if you’re an experienced Anvil user, why not extend the app? Here is some inspiration for features to add:
- Make the board view more informative. Try displaying the number of tasks in each project on the card.
- Add deadlines. Use a Date Picker component to allow users to set a deadline on a project. If the deadline has passed, make the colour of the deadline red. Expand this even further by adding a new type of column to project tables that lets you set a date for each task.
- Archive tasks. Add a function that lets users archive tasks without deleting them. They shouldn’t show up in the normal table but still be viewable somehow.
- Allow multiple tables per project. Right now, the app only allows one table per project. Allow users to add or delete tables to a project. Think about how this would change your database structure.
Show us what you’ve built! Have you created a cool internal tool with Anvil or extended this Task Manager app? Let us know! We’d love to see what you’ve built on our Show and Tell Community Forum.
Want to dig into how this app works? Our tutorials show you all the pieces this app is made from, and more:
Build Database-Backed Apps
Build a Simple Feedback Form
- Build your User Interface
- Write client-side Python
- Write server-side Python
- Store data in a database
- Deploy your app