A Task Manager App Built with Python
Tags: python, webdev, showdev, programming
Published: 2022-11-15 11:18:43


# Building a task management app with Anvil

[Anvil](https://anvil.works?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) is a powerful and versatile tool for building full-stack web applications. With Anvil, you can [quickly and easily create your UI](https://anvil.works/blog/build-a-web-ui-with-python?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) 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](https://anvil.works/for/internal-tools?utm_source=crosspost:dev.to:/learn/examples/task-manager-app). This simple but powerful task management app demonstrates some of what you can do with Anvil. 

![Opening and editing a project in the task management app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kqwaxhqu7i0exi1r7bmj.png)

Open the source code and check out the app for yourself: https://anvil.works/build#clone:ILO62UVSCDQLTFHF%3dPJNDVGDLQSB7GG4RAQLSNHXA

I built [the app’s UI](https://anvil.works/beta-docs/client/ui?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) 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](https://anvil.works/beta-docs/server?utm_source=crosspost:dev.to:/learn/examples/task-manager-app). 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](https://anvil.works/beta-docs/client/components/data-grids?utm_source=crosspost:dev.to:/learn/examples/task-manager-app). Users can click on the cells in the table to edit their contents. 

![Creating a new project and adding a column.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ptlqrl62tinamgk164bg.gif)

On the main page, there is a board view of all the projects. Here, you can add comments to or delete projects. 

![Adding a comment and deleting a project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kusnz8ruziu2vo7uhug.gif)

---

## How it's built

### Building the database

Every Anvil app comes with a [built-in database system](https://anvil.works/beta-docs/data-tables?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) 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. 


![The Columns Data Table stores the title and type of all columns in all projects" alt="Screenshot of the Columns Data Table showing two columns: title and type](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tyn2338fle8nspricq6j.png)


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](https://anvil.works/beta-docs/data-tables/links-between-tables?utm_source=crosspost:dev.to:/learn/examples/task-manager-app). This connects each row in the Columns Data Table with its corresponding project.


![The Projects Data Table stores the name of each project and links to the Columns Data Table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uhmwvtmq099sc0pceclb.png)


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.


![The Rows Data Table links to a row from the Projects table and stores the data for each row in all the projects](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vkg0e6dsz74q7ew5g7id.png)


### Writing back-end Python

Anvil’s [Server Modules](https://anvil.works/beta-docs/server?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) are a full server-side Python environment. Server Modules cannot be edited or seen by the user, so we can [trust them](https://anvil.works/beta-docs/security#client-vs-server-code?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) 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.

```python
@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
```

The `@anvil.server.callable` decorator means that this function can [easily be called from client-side code](/beta-docs/server#calling-server-functions-from-client-code):

```python
anvil.server.call('add_column_to_db', title, self.project, type)
```

### Creating the UI with client-side Python

I [created the app’s UI](https://anvil.works/beta-docs/client/ui?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) 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:

![Dragging-and-dropping a Data Grid from the Toolbox onto the ProjectView Form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58k4d3on4dns99xjytv4.gif)

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](https://anvil.works/beta-docs/client/components/basic#link?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) to all the projects in the app. 


![Adding a new project from the left navigation menu then renaming it. The links in the menu are cleared and regenerated when the project is renamed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2kxjqvfalr70e7dkt5r.png)

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](https://anvil.works/beta-docs/client?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) that runs in the user’s browser.

```python
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](https://anvil.works/beta-docs/client/custom-components?utm_source=crosspost:dev.to:/learn/examples/task-manager-app). 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.

![Clicking on the Custom Component allows the text to be edited. Pressing enter saves the new text.](https://anvil-website-static.s3.eu-west-2.amazonaws.com/learn/examples/task-manager-app/editable-link.gif)


### Adding the User Management Service

Anvil also provides built-in [user management](https://anvil.works/beta-docs/users?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) 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](https://anvil.works/beta-docs/users/the_users_table?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) 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.

![Assigning a task to a user](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpmfw6j6st75zqolmhyc.gif)

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.


![A login form for signing into the app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zjn8ge2v9gjngsj44h6.png)
     
---

## What next?

Clone the app to check out the source code and try it for yourself: https://anvil.works/build#clone:ILO62UVSCDQLTFHF%3dPJNDVGDLQSB7GG4RAQLSNHXA


If you’re new to Anvil, why not try a [5-minute tutorial](https://anvil.works/learn/tutorials/feedback-form?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) 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](https://anvil.works/beta-docs/client/components/basic#datepicker?utm_source=crosspost:dev.to:/learn/examples/task-manager-app) 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](https://anvil.works/forum/c/show-and-tell/6?utm_source=crosspost:dev.to:/learn/examples/task-manager-app).

-----

Want to dig into how this app works? Our tutorials show you all the pieces this app is made from, and more:

* [Tutorial: Build a Simple Feedback Form](https://anvil.works/learn/tutorials/feedback-form?utm_source=crosspost:dev.to:/learn/examples/task-manager-app)

* [Tutorial: Data Dashboard](https://anvil.works/learn/tutorials/dashboard?utm_source=crosspost:dev.to:/learn/examples/task-manager-app)

* [Tutorial: Build Database-Backed Apps](https://anvil.works/learn/tutorials/database-backed-apps?utm_source=crosspost:dev.to:/learn/examples/task-manager-app)