PythonでNotionのAPIを操作する方法

さいきんNotionを使い始めました。

Notionは、タスク、Wiki、およびデータベースを統合するマークダウンサポートを備えたメモアプリケーション及びサービス。 同社はこのアプリを、メモ作成、プロジェクト管理、タスク管理のためのオールインワンワークスペースと説明している。


いろいろと使い方を勉強している途中ですが、APIが公開されているということで、NotionのAPIをPythonから操作してみようと思います。
とりあえずは簡単な操作ということで、Notionデータベースにプロパティを指定してデータを追加してみます。

Python使用ライブラリ

requestsを使います。 適宜pip installしておきましょう。

pip install requests


シークレットキーの取得

まずはAPIシークレットキーをデベロッパーサイトから入手しましょう。
こちらからアクセスできます。



Create new integrationをクリックします。



Nameに適当なサービス名を入れて、Associated workspaceでワークスペースを選択してSubmitを押します。



シークレットキーが発行されます。 後で使うのでメモ帳か何かに保存しておきましょう。



下の方にスクロールして、Internal integrationにチェックが入っていることを確認しておきます。
以上でここまでは終了です。

Notionで適当なデータベースを作る

次にNotion上に適当なデータベースを作成しましょう。



サイドバーからAdd a pageと押すとこのような画面になります。 DATABASEからTableを選択します。



今回はToDo Listっぽい感じで試してみます。
Nameに適当に入力し、OPENを押します。



そうするとこのような画面からプロパティが編集できます。
Notionのデータベースのプロパティについて、Excelの表の列みたいなものだと思えばよいと思います。
名前とタイプを指定することができます。

このプロパティを元に表示を切り替えたり、並び替えたりできたり、といった感じです。
Tagsとなっている部分をクリックすることで編集ができます。



今回はToDo Listなのでタスクをいつまでにやるとか管理したいです。
なので、名前を日付に直して、Dateを選択します。



プロパティは追加していくことができます。
Todo Listだと完了とか未完了のステータスも管理したいです。
なので、タイトルを状態Selectと選択していきます。



そうすると先ほど追加した日付状態がセットされます。
日付のセルをクリックするとカレンダーが出てきて、日付を選択できます。




状態のほうはSelectなので、適宜選択肢を追加していく感じです。 とりあえず完了と未完了としましょう。



ここまででこんな感じになりました。

データベースとアカウントを紐づける


次にページ右上のShareをクリックします。



先ほど追加したAPI integrationを選択してInviteします。
次に右上の・・・をクリックして、Copy linkをクリックします。



このようなURLのはずです。

<https://www.notion.so/15hogef23cc94efuga64hoge36703844?v=ca16f2b68affuga9hoge8bfugaf9d3fd>

上の部分で、so/?の間がDatabaseのidになります。

<https://www.notion.so/{15hogef23cc94efuga64hoge36703844}?v=ca16f2b68affuga9hoge8bfugaf9d3fd>

{}で囲った部分ということです。
これで準備がそろいました。

APIをPythonから叩く

公式のAPIリファレンスを参考に簡単なものを試してみました。

データベースの取得

リクエストURLはhttps://api.notion.com/v1/databases/{database_id}となります。
GETリクエストを送って結果を確認してみます。

import requests
from pprint import pprint

def get_request_url(end_point):
    return f'<https://api.notion.com/v1/{end_point}>'

notion_api_key = 'your api secret'
databases_id = 'your database id'
headers = {"Authorization": f"Bearer {notion_api_key}",
           "Content-Type": "application/json",
           "Notion-Version": "2021-05-13"}

response = requests.request('GET', url=get_request_url(f'databases/{databases_id}'), headers=headers)

pprint(response.json())

>>>

{'created_time': '2021-07-01T13:59:10.814Z',
 'id': 'your database id',
 'last_edited_time': '2021-07-01T14:40:00.000Z',
 'object': 'database',
 'parent': {'type': 'workspace', 'workspace': True},
 'properties': {'Name': {'id': 'title', 'title': {}, 'type': 'title'},
                '日付': {'date': {}, 'id': 'qK>v', 'type': 'date'},
                '状態': {'id': '[kjD',
                       'select': {'options': [{'color': 'pink',
                                               'id': 'c5ffabea-ccb9-4fd5-9603-ef83ce068fae',
                                               'name': '完了'},
                                              {'color': 'brow

n',
                                               'id': '82cf5f31-b926-482c-9cff-a3b942acc739',
                                               'name': '未完了'}]},
                       'type': 'select'}},
 'title': [{'annotations': {'bold': False,
                            'code': False,
                            'color': 'default',
                            'italic': False,
                            'strikethrough': False,
                            'underline': False},
            'href': None,
            'plain_text': 'ToDo List',
            'text': {'content': 'ToDo List', 'link': None},
            'type': 'text'}]}


それっぽいデータが返ってきました。
propertiesの部分に先ほど設定した日付とか状態という値が入っています。

次にデータを追加してみましょう。

データベースにページを追加する

リクエストURLはhttps://api.notion.com/v1/pages/となります。
json形式でデータを送る必要があるので、jsonをimportしておきましょう。

import json

...省略

body = {
    "parent": {
        "database_id": databases_id},
    "properties": {
        "Name": {"title": [
            {"text": {"content": "POST メソッド"}}
        ]
        }
    }}

response = requests.request('POST', url=get_request_url('pages'), headers=headers, data=json.dumps(body))
pprint(response.json())

>>>
{'archived': False,
 'created_time': '2021-07-01T15:44:13.837Z',
 'id': 'bea3c0e2-f650-453e-b0fc-f0bec72d9811',
 'last_edited_time': '2021-07-01T15:44:13.837Z',
 'object': 'page',
 'parent': {'database_id': 'your database id',
            'type': 'database_id'},
 'properties': {'Name': {'id': 'title',
                         'title': [{'annotations': {'bold': False,
                                                    'code': False,
                                                    'color': 'default',
                                                    'italic': False,
                                                    'strikethrough': False,
                                                    'underline': False},
                      

              'href': None,
                                    'plain_text': 'POST メソッド',
                                    'text': {'content': 'POST メソッド',
                                             'link': None},
                                    'type': 'text'}],
                         'type': 'title'}}}


想像はしていたのですが、階層が深いです。
一応は下の写真のように追加ができました。


日付や状態を指定して追加

日付や状態を指定して加える場合は以下のようにします。

body = {
    "parent": {
        "database_id": databases_id},
    "properties": {
        "Name": {"title": [
            {"text": {"content": "日付と状態"}}
        ]
        },
        "日付": {
            "date": {"start": datetime.datetime(year=2021, month=7, day=7).isoformat()}
        },
        "状態": {"select": {"name": "完了"}}
    }}
response = requests.request('POST', url=get_request_url('pages'), headers=headers, data=json.dumps(body))




選択肢にない状態を加えると、新たに生成されます。 階層が深くなってきたので変数を使います。
多少、見やすくなります。

property_name = {"title": [{"text": {"content": "選択肢を追加"}}]}

property_date = {"date": {"start": datetime.datetime(year=2021, month=7, day=7).isoformat()}}

property_select = {"select": {"name": "新しい選択肢"}}

body = {
    "parent": {
        "database_id": databases_id},
    "properties": {
        "Name": property_name,
        "日付": property_date,
        "状態": property_select
    }}

このように追加されます。





TOPページ