Skip to content

Introduction to databases

Databases are one of the most versatile and powerful features of Notion. Working programmatically with your databases extends Notion's functionality to infinity as you can use Python for all kinds of transformations, use external data services and what not. Ultimate Notion unleashes the full power of Python for use with Notion's databases. So let's see what we can do.

Searching for a database

Assume we have a database called Contacts DB.

import ultimate_notion as uno

notion = uno.Session.get_or_create()  # if NOTION_TOKEN is set in environment

contacts_dbs = notion.search_db('Contacts DB')

assert [db.title for db in contacts_dbs] == ['Contacts DB']

The method search_db will always return a list as Notion gives no guarantees that the title of a database is unique. Practically though, most users will give databases unique names and to accommodate for this, the returned list provides a method .item(), which will return the item of a single-item list or raise an error otherwise. Another possibility would be to retrieve the database by its unqiue id.

contacts_db = notion.search_db('Contacts DB').item()
# or in case the unique ID of the database is known
contacts_db = notion.get_db(contacts_db.id)

The Database object provides access to many attributes like title, icon, description, etc.

assert contacts_db.description == 'Database of all my contacts!'

Creating a database and adding pages

A simple database with the default columns Name for the title of pages and the Multi-select column Tags, can be created using create_db. To tell Notion where to put the database, we have to provide an existing page. Let's assume we have a page called Tests, which is shared with our integration:

root_page = notion.search_page('Tests').item()
my_db = notion.create_db(parent=root_page)

Using the my_db object, we can now set its attributes, e.g.:

my_db.title = 'My DB'
my_db.description = 'This is my database for cool Python libraries!'

Info

Unfortunately, the Notion API does not support setting the icon or the cover of a database.

We can now simple add a new page to this database and set some attributes:

new_page = my_db.create_page(name='Ultimate Notion')
new_page.description = 'Notes about Ultimate Notion'
new_page.icon = '🚀'
new_page.cover = 'https://www.notion.so/images/page-cover/woodcuts_2.jpg'

This is how My DB looks right now.

Notion My DB

But how can I figure out which keyword arguments to pass to create_page? For this we can take a look at the [schema] of the database, which also allows us to create new pages in a neat way. As our database holds tools, we can express this by naming the variable for the schema accordingly. An example illustrates this:

Tool = my_db.schema
Tool.show()

This shows us that our database has two columns Name and Tags as well as the name of the arguments for create_page.

Name    Property     Attribute
------  -----------  -----------
Tags    MultiSelect  tags
Name    Title        name

A new page can now also be created using Tool, i.e.

new_tool = Tool.create(name='Ultimate Notion')

This is basically just an alias for create_page but can make your code much more expressive.

Viewing the pages of a database

Assume we have a simple database listing tasks like this:

Notion task database

To access the tasks, i.e. the pages within this database, we can use the fetch_all method to generate a View. It's as simple as:

task_db = notion.search_db('Task DB').item()
task_view = task_db.fetch_all()

To get a quick overview of our tasks, we can use show. On the console, this will print:

Task                              Status       Priority    Urgency    Due Date
--------------------------------  -----------  ----------  ---------  -------------------------
Clearing out the cellar           In Progress  ✶ Low       🔥 -2w2d   2023-11-16 17:10:00+01:00
Run first Marathon                Done         ✶ Low       ✅         2023-11-24 17:10:00+01:00
Pay yearly utility bills          Blocked      ✹ High      🔥 -5d     2023-11-27 17:10:00+01:00
Call family                       Done         ✶ Low       ✅         2023-12-01 17:10:00+01:00
Complete project report for work  In Progress  ✷ Medium    🔹 Today   2023-12-02 17:10:00+01:00
Build tool with Ultimate Notion   In Progress  ✶ Low       🕐 1d      2023-12-03 17:10:00+01:00
Clean the house                   In Progress  ✶ Low       🕐 5d      2023-12-07 17:10:00+01:00
Read book about procastination    Backlog      ✷ Medium    🕐 2w2d    2023-12-18 17:10:00+01:00
Plan vacation                     Backlog      ✹ High      🕐 3w3d    2023-12-26 17:10:00+01:00

or in Jupyter Lab this will be shown as:

Notion task view

Special columns, for the index, the page's id and its icon, can be activated using with_index, with_id, with_icon, respectively.:

task_view.with_index().with_id().with_icon()

Notion task view extended

The index can now be used to retrieve a specific page with get_page or we could just convert the whole view to a Pandas dataframe with to_pandas.

Working with views

Views help you setting the stage for various operations like exporting with the help of the various to_* methods or applying a function to the contained pages using apply. With select the view can be restricted to certain columns whereas head (with alias limit) and tail can be used to restrict the number of rows in the view, e.g.:

task_view.select('Task', 'Status').head(3).show(simple=True)
Task                      Status
------------------------  -----------
Clearing out the cellar   In Progress
Run first Marathon        Done
Pay yearly utility bills  Blocked

All methods return a new view without modifying the current one, which allows keeping different views at the same time. To reset the current view object, the reset method can be used. To reload the view, i.e. re-execute the query that led to the view, use reload.

Find out about more about the functionality of View by reading the API references but keep in mind that some methods are just stubs.