Notion is a surprisingly good choice for adding a simple database when using Django. It's:
- quick
- free
- helps you create a product that needs some state fast.
- simple to see your data and edit it because you are just using Notion.
- shareable. You can share your database and let them edit it too. This is also useful for when working with non-technical customers.
- easy. You don't have to spend time setting up a database (you can add Postgres later).
I'll show your how to add Notion as your Django database in less than 8 minutes.
This follows my previous guide and talk at Django London 🇬🇧 on using Google sheets as a database that I gave in November.
Here's what we'll make:
Let's begin 🛫
Optional video tutorial (featuring me) below 📽️:
0. Setup the Django project that we'll connect to our Notion database
Install the necessary packages
pip install django python-dotenv notion-client
django-admin startproject core .
python manage.py startapp sim
We'll be using the notion client as a wrapper for the Notion API.
Register your app in your settings.py file
- Add
'sim'
to theINSTALLED_APPS
list in thesettings.py
file:
INSTALLED_APPS = [
# ...
'sim',
# ...
]
1. Add your Notion API key to the Django project
- Go to the Notion integrations page and click "Create a new integration"
- Go to capabilities and tick the box saying "Read user information including email addresses"
- Enter a name for the integration and click "Submit"
-
Copy the "Internal Integration Token"
-
Create a new file called
.env
in thecore
directory - Add the following line to the
.env
file, replacing<your-token>
with the token you copied from Notion:
NOTION_TOKEN=<your-token>
- Add the following line to the top of the
settings.py
file to load the environment variables:
from dotenv import load_dotenv
import os
load_dotenv()
Test your connection to the Notion API
Open your Django shell:
python manage.py shell
Run the following commands:
import os
from notion_client import Client
notion = Client(auth=os.environ["NOTION_TOKEN"])
list_users_response = notion.users.list()
print(list_users_response)
You should see a list of users in your Notion workspace that looks something like this:
{
"object": "list",
"results": [
{
"object": "user",
"id": "a1b2c3d4-1234-5678-90ab-cdef12345678",
"type": "person",
"name": "John Doe",
"avatar_url": "https://example.com/image.png"
}
],
"next_cursor": null,
"has_more": false
}
See here for:
- the
notion_client
library documentation: https://github.com/ramnes/notion-sdk-py - the full list of API commands (which the
notion_client
library wraps): https://developers.notion.com/reference/intro
Troubleshooting: I get an error like "AttributeError: 'str' object has no attribute 'logger'. Did you mean: 'lower'?"
The notion_client Client requires the `auth` keyword argument, i.e., `Client(auth=os.environ["NOTION_TOKEN"])`2. Connect your Notion database to Django
Connect your database to an integration
To use an API with a certain database, you need to give that database permission to work with your API integration. This isn't done when you create the API token, but you can find how to do it in the instructions.
Here's how to let your API integration access a database:
- Open the database you want in Notion
- Look for a menu with three dots (•••) at the top-right of the page and click it.
- From the menu that appears, choose "Add connections."
- Pick your API integration from the list that shows up.
Add your Notion database ID to the Django project
- Append the following line to the
.env
file, replacing<your-token>
with the token you copied from Notion:
NOTION_DATABASE_ID=<your-token>
Get your Notion database ID to query with Django
To find a database ID, navigate to the database URL in your Notion workspace. The ID is the string of characters in the URL that is between the slash following the workspace name (if applicable) and the question mark. The ID is a 32 characters alphanumeric string.
Oddly, there's no clear way to list all databases and their IDs using the Notion API. The simplest way is to get the database id from the database's URL
You can get this by:
- clicking 'share'
- copying the link to your database
- finding the id in the link
Here's a link to show which part of the url is your database id: https://developers.notion.com/reference/retrieve-a-database
Test your connection to your Notion database using Django
Back to the Django shell, run the following commands:
import os
from notion_client import Client
notion = Client(auth=os.environ["NOTION_TOKEN"])
notion.databases.query(os.environ["NOTION_DATABASE_ID"])
3. Render your Notion data in a Django template
Connect your urls to your views
- Update the
sim/urls.py
file:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
- Update the
core/urls.py
file:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('sim.urls')),
]
Create a template to render your Notion data to HTML
- Create a new directory called
templates
in thesim
directory - Create a new file called
index.html
in thetemplates
directory - Update the
index.html
file:
<!DOCTYPE html>
<html>
<head>
<title>Your applicants</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
}
.container {
width: 80%;
margin: 20px auto;
background: white;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.employee-row {
display: flex;
align-items: center;
background-color: #fff;
margin-bottom: 10px;
padding: 10px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
a {
text-decoration: none;
color: #000;
}
.employee-row:hover {
background-color: #f9f9f9;
}
.profile-info {
display: flex;
align-items: center;
margin-right: 20px;
}
.profile-info img {
width: 80px;
height: 80px;
border-radius: 40px;
margin-right: 15px;
object-fit: cover;
}
.employee-details {
display: flex;
flex-direction: column;
}
.employee-details > div {
margin-bottom: 5px;
}
</style>
</head>
<body>
<div class="container">
{% for row in rows %}
<a class="employee-row" href="{{ row.properties.profile_url.url }}" target="_blank">
<div class="profile-info">
<img src="{{ row.properties.photo.files.0.file.url }}" alt="{{ row.properties.name.title.0.plain_text }}">
</div>
<div class="employee-details">
<div><strong>{{ row.properties.name.title.0.plain_text }}</strong></div>
<div>{{ row.properties.role.rich_text.0.text.content }}</div>
<div>{{ row.properties.description.rich_text.0.text.content }}</div>
</div>
</a>
{% endfor %}
</div>
</body>
</html>
Create a view to send your Notion API as context to the Django template
- Update the
sim/views.py
file:
from django.shortcuts import render
from notion_client import Client
import os
def index(request):
notion = Client(auth=os.environ['NOTION_TOKEN'])
data = notion.databases.query(os.environ.get('NOTION_DATABASE_ID'))
return render(request, 'index.html', {'rows': data['results']})
Run the Django server
python manage.py runserver
4. Add data to your Notion database
Now we need some data to your database in Notion.
Feel free to add your own fields to the database and update the template to use them. To work with the variables I added to the Django template, you need to add the following properties to your database:
- name (title) (Make sure it's lowercase)
- photo (file)
- role (rich text)
- description (rich text)
- profile_url (url)
Here's the data I added to my database if you want to copy it:
name,photo,role,description,profile_url
Andrew Michs, ,Software Developer,"Translate the arcane mutterings of stakeholder meetings into elegant code, presumably using some form of dark magic (also known as JavaScript). Work in a team that believes 'Agile' is a type of yoga. Required: an undying love for debugging at 3 AM.",https://www.photondesigner.com
Kelly Conway, ,Marketing Manager,"Cut through the digital noise with the sharp blade of your wit, crafting campaigns that might actually be read. Analyze trends with the enthusiasm of a cat watching a documentary on bird migration. Bonus points if you can say 'synergy' without cringing.",https://www.photondesigner.com
Hella Paulson, ,Human Resources Coordinator,Divine the future of candidates from the entrails of their CVs. Spread joy and policies with equal fervor. Experience in resolving coffee machine disputes preferred.,https://www.photondesigner.com
Teshra Coda, ,Graphic designer,"Transform client 'feedback' into visual gold, often by guessing what they meant by 'make it pop'. Must enjoy spelunking in the caverns of Adobe Creative Suite. Warning: Exposure to Comic Sans may occur.",https://www.photondesigner.com
5. View the Notion data in your Django template
- Go to http://127.0.0.1:8000/ in your web browser to view the final result
Troubleshooting: I get the error "TemplateDoesNotExist at /"
Make sure you have: 1. the `templates` directory in the `sim` directory 2. the `index.html` file is in the `templates` directory 3. Added 'sim' to the `INSTALLED_APPS` list in the `settings.py` file (See above) 4. are visiting the correct URL (See above)Edit your Notion database and see the changes in your Django template
With your Django app now connected to your Notion database, any changes you make in Notion will reflect in your Django template.
Congrats! You've connected your Notion database to your Django project
You've combined Notion and Django, creating a flexible database 🌟.
Let's go bigger: imagine allowing your users to contribute and edit content. Envision the potential enhancements to your app. Users could add new items or tweak existing ones.
You could create a digital gallery, or perhaps a platform similar to Instagram that supports video uploads.
Build your Django frontend even faster
I want to release high-quality products as soon as possible. Probably like you, I want to make my Django product ideas become reality as soon as possible.
That's why I built Photon Designer - an entirely visual editor for building Django frontend at the speed that light hits your eyes. Photon Designer outputs neat, clean Django templates.