Python での Notion API の使い方を紹介します。
既存の Notion データベースにデータを追加、更新、削除します。
追加、更新する時に必要なデータベースのプロパティを分かりやすく引数にする方法も考えたので紹介します。
Notion データベースにプログラムでデータが入れられると使い勝手が上がりますよ。
追加される Notion データベースと追加するデータは次のリンクで紹介したものです。
- データベースのリンク:『ブログ記事管理🔗』
- データベースの記事:『ブログの記事を管理する(使い方)【Notionデータベース】🔗』
- 追加するデータの記事:『はてなブログのスターとブックマークの数を取得するアプリ【フリー】🔗』
アプリを使って自分のブログの管理をしたい方は、こちらを参照してください。
- データ追加するアプリの記事:『ブログの記事を管理するNotionデータベースとデータ更新アプリ【フリー】🔗』
目次
- ◆Python で Notion API を操作する
- ◆notion-client パッケージの使い方
- ◆Notion API 操作について
- ◆Notion API の各種設定値
- ◆データベースのプロパティに合ったプロパティ値の作り方
- ◆Python で実践
- ◆Notion インテグレーションの作成とデータベース ID の取得
- ◆環境変数の設定
- ◆さいごに
- ◆参考
◆Python で Notion API を操作する
Python で Notion API を操作するには、request パッケージでも対応が可能です。
しかし、notion-client パッケージ の方が使いやすいです。
notion-client は、次のように言っています。
💬Notion API のシンプルで容易なクライアントである
💬JavaScript SDK の Python バージョンという位置づけなので、双方の使い方はよく似ている
Notion API リファレンスには、Python のサンプルとして request を使用した例が載っています。
notion-client を使用する場合、Notion API リファレンスのサンプルは、上記のこともあって、JavaScript を見た方が理解しやすいです。
◆notion-client パッケージの使い方
notion-client で Notion API を操作するには、Client クラスのインスタンスを作成して操作します。
例:notion = Client(auth=self.AUTH)
◇Clientクラスのコンストラクタの引数
オプション | デフォルト値 | タイプ | 説明 |
---|---|---|---|
auth |
なし | 文字列 | Notionのインテグレーショントークンを指定 |
log_level |
logging.WARNING | int | インスタンスが生成するログの詳細度 デフォルトでは、ログはstdoutに出力 |
timeout_ms |
60_000 | int | RequestTimeoutErrorを発行する前に待機するミリ秒数 |
base_url |
https://api.notion.com |
string | APIリクエストを送信するためのルートURL モックサーバーでテストする場合用 |
logger |
Log to console | logging.Logger | カスタムロガー指定可能 |
◇Notion データベースの読み込み
notion-client で Notion データベースを読み込む簡単な例です。
Client クラスのインスタンスに databases 属性(データベースオブジェクト)があります。
読み込みは、その databases 属性の query() メソッドを呼び出します。
呼び出しには、データベース ID をキーワード引数に指定します。
正常終了であれば、データベースの内容が辞書型で返ってきます。
notion.databases.query( **{ 'database_id' : '' # データベースID } )
◇Notion データベースの書き込み
notion-client で Notion データベースにデータを書き込む簡単な例です。
Client クラスのインスタンスに page 属性(ページオブジェクト)があります。
書き込みは、その page 属性の create() メソッドを呼び出します。
呼び出しには、データベース ID、プロパティ値をキーワード引数に指定します。
notion.pages.create( **{ 'parent': {'database_id': ''}, # データベースID 'properties': {} # ここにカラム名と値を記載 } )
➡ propertiesに設定する辞書が難しい
◆Notion API 操作について
Notion API 操作についてまとめました。
これらの操作は、notion-client パッケージの Client クラスのインスタンスから行います。
Notion API には、 database object
, page objects
, block object
が存在し、それを介して Notion と対話します。
インスタンスでは、ぞれぞれ databases
, pages
, blocks
という属性が対応します。
何をどこにリクエストするのかということを気にしないで操作できます。
以降の表で下線が付いているものは今回使用したものです。
それ以外の操作はリファレンスからの抜粋です。
表の中の notioon は、Client クラスのインスタンスです。
◇Database object を介する操作
データベースオブジェクトは、データベース ID を指定して操作します。
Notion APIの記載 | 対応メソッド | 内容 |
---|---|---|
Query a database(POST) | notion.databases.query() | ▶問合せ▶データベースに含まれるページの配列を取得 フィルター条件と並べ替え基準を指定可能 |
Create a database(POST) | notion.databases.create() | ▶生成▶指定した親ページのサブページとしてデータベースを作成 指定したプロパティスキーマを使用 |
Update database(GET) | notion.databases.update() | ▶更新▶指定したパラメータで既存のデータベースを更新 |
Retrieve a database(GET) | notion.databases.retrieve() | ▶取得▶指定した ID で Database オブジェクトを取得 |
◇Page object を介する操作
ページオブジェクトは、Notion の一つのページに該当します。
一つのページには、プロパティ値が存在します。また、親が存在します。
親がデータベースの場合、プロパティ値はデータベースの表形式の1行に該当します。
ページオブジェクトは、ページ ID を指定して操作します。
Notion APIの記載 | 対応メソッド | 内容 |
---|---|---|
Retrive a page(GET) | notion.pages.retrive() | ▶取得▶指定した ID で Page オブジェクトを取得 引数:page_id |
Create a page(POST) | notion.pages.create() | ▶生成▶指定したデータベースに新しいページを作成するか、既存のページの子として作成 引数:parent, properties, children, icon, cover |
Update page(PATCH) | notion.pages.update() | ▶更新▶指定したページのページ プロパティ値で更新 指定されていないプロパティは変更されません 引数:page_id, properties, archived, icon, cover |
Retrieve a pate property item(GET) | notion.pages.properties.retrieve() | ▶取得▶指定した page_id および property_id の property_item オブジェクトを取得 |
◇Block object を介する操作
ブロックオブジェクトは、Notion 内のコンテンツを表します。
ブロックには、テキスト、リスト、メディアなどがあります。
ページも一種のブロックです
ブロックオブジェクトは、ブロック ID を指定して操作します。
ブロック ID の取得方法が理解できていないので、「削除」以外は使っていません。
削除は、ページの削除で使用するので、ページ ID をブロック ID として使えたので使いました。
また、ページオブジェクトにも削除はあるのですが、ブロックオブジェクトを使うように指示されています。
Notion APIの記載 | 対応メソッド | 内容 |
---|---|---|
Retrieve a block(GET) | notion.blocks.retrive() | ▶取得▶指定した ID で Block オブジェクトを取得 |
Update a block(PATCH) | notion.blocks.update() | ▶更新▶ブロック タイプに基づいて、指定した block_id のコンテンツを更新 |
Retrieve block children(GET) | notion.blocks.children.list() | ▶取得▶指定した ID で、ブロックに含まれる子ブロック オブジェクトのページ分割された配列を返す |
Append block children(PATCH) | notion.blocks.children.append() | ▶追加▶新しい子ブロックを作成し、指定した親 block_id に追加 |
Delete a block(DELETE) | notion.blocks.delete() | ▶削除▶指定した ID で Block オブジェクトを archived: true に設定 ※ Notion UI アプリケーションでは、これによりブロックが「ゴミ箱」に移動され、引き続きアクセスして復元することができます 引数:block_id |
◆Notion API の各種設定値
ここでは、Notion データベースに対して API を使用することを前提に説明します。
◇ページオブジェクト
データベースオブジェクトの Query() で問合せするとページオブジェクトの配列が返ります。
ページオブジェクトのプロパティの一部です。
プロパティ | 値 |
---|---|
object | "page"固定 |
id | id |
create_time | 作成日(世界標準時間) |
last_edited_time | 更新日(世界標準時間) |
parent | 親情報。{"type":"database_id", "database_id":???} |
archived | アーカイブ状態(削除する時に使用) |
properties | プロパティ。{プロパティ名:プロパティ値} |
◇プロパティ値
ページオブジェクトにある proterties プロパティはオブジェクトで、キーはNotion データベースで定義したプロパティ名、値はそのプロパティの型に応じたオブジェクト(プロパティ値)になります。
▽サンプル
"properties": { # JSONにはコメントを付けられないのでPythonで記述しています "カテゴリ": { # プロパティ名(キー) これ以降がプロパティ値 "id": "UNHI", "type": "multi_select", # 型名 "multi_select": [ # 型に対する内容 { "id": "87ef771a-1e60-492a-b06a-2d8ed9dcd58d", "name": "ブログ", "color": "brown" }, { "id": "e869c74e-480b-43e4-a653-70f4f89406c4", "name": "シニア", "color": "purple" } ] },…
キー | 値 |
---|---|
id | id |
type | 型名 "title", "rich_text", "number", "select", "multi_select", "date", "people", "files", "checkbox", "url", "email", "phone_number", "formula", "relation", "rollup", "created_time", "created_by", "last_edited_time", "last_edited_by", "status" |
型 | 型に対する内容 |
◎型に対する内容の例
型ごとに異なるオブジェクトを持っています。
型名 | 設定例 "名前":プロパティの名前 |
---|---|
title | "名前":{ "title":[{ "type":"text", "text":{ "content":"The title" } }] } |
rich_text | "名前":{ "rich_text":[{ "type":"text", "text":{"content":"xxx"} }, { "type":"text", "text":{"content":"xxx"}, "annotations":{"italic":true} }] } |
number | "名前":{ "number":1234 } |
select | "名前":{ "select":{"name":"Option 1"} } |
multi_select | "名前":{ "multi_select":[{"name":"B"},{"name":"C"}] } |
date | "名前":{ "date":{ "stat":"2021-04-25", "end":"2021-05-07" } } |
files | "名前":{ "files":[{ "type":"external", "name":"Space Wallpaper", "external":{ "url":"https://website.domain/images/space.png" } }] } |
url | "名前":{ "url":"https://notion.so/notiondevs" } |
◎time zomeについて
日付型のプロパティ値には、time_zome
プロパティが存在します。
現在、Notion API で、このプロパティは機能しません。
何もしないと標準時で指定された日時として扱われます。
対応方法は、指定する日時に標準時との差を付加します。
例:2022-07-10 15:30:41+09:00
◆データベースのプロパティに合ったプロパティ値の作り方
Notion API でデータベースの操作を行う場合、そのデータベースに定義されたプロパティに合ったプロパティを使って指示しなければなりません。
次節に取得した Notion データベースのプロパティを載せていますが、なかなか複雑です。
プロパティの型によってその属性(色など)もプロパティに含まれているためです。
プロパティの型にごとに設定するメソッドを作ろうかとも考えたのですが、型の数だけ作るのも大変そうだし、汎用的なメソッドにするのも難しそうなので、今回は止めました。
その代わり、直感的にわかりやすい方法を思いつきました。
それは、Notion API で取得した Notion データベースのプロパティを基にデータ更新に使えるプロパティの辞書を作る事です。
【手順】
- Notion データベースからページのプロパティのデータを取得する
- 取得したデータを JSON ファイルに出力する
※ JSON ファイルにするのは辞書を可視化するため - JSON ファイルをデータ更新に必要な要素だけにする
- 必要な要素だけになったものを Python の辞書に置き換える
- さらにメソッド化する
※以下、取得したデータを基に説明しますが、セキュリティ的に怪しいデータは「??????????」に変更してあります。ご了承ください。
◇取得したデータ
{ "object": "list", "results": [ { "object": "page", "id": "??????????", "created_time": "2022-05-09T06:42:00.000Z", "last_edited_time": "2022-07-12T01:12:00.000Z", "created_by": { "object": "user", "id": "??????????" }, "last_edited_by": { "object": "user", "id": "??????????" }, "cover": null, "icon": null, "parent": { "type": "database_id", "database_id": "??????????" }, "archived": false, "properties": { "スター": { "id": "%40RKt", "type": "number", "number": 5 }, "掲載日": { "id": "F%3Eh%3D", "type": "date", "date": { "start": "2021-05-13T10:28:00.000+09:00", "end": null, "time_zone": null } }, "アイキャッチ画像": { "id": "LIyv", "type": "files", "files": [ { "name": "https://cdn-ak.f.st-hatena.com/images/fotolife/??????????.png", "type": "external", "external": { "url": "https://cdn-ak.f.st-hatena.com/images/fotolife/??????????.png" } } ] }, "ブックマーク": { "id": "S%3ELZ", "type": "number", "number": 1 }, "カスタムURL": { "id": "SKu%7C", "type": "rich_text", "rich_text": [ { "type": "text", "text": { "content": "blog/gimp/shukusho", "link": null }, "annotations": { "bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default" }, "plain_text": "blog/gimp/shukusho", "href": null } ] }, "カテゴリ": { "id": "UNHI", "type": "multi_select", "multi_select": [ { "id": "??????????", "name": "ブログ", "color": "brown" }, { "id": "??????????", "name": "GIMP", "color": "pink" }, { "id": "??????????", "name": "シニア", "color": "purple" } ] }, "最終更新日": { "id": "XH%3Ex", "type": "date", "date": null }, "タグ": { "id": "bua%3D", "type": "multi_select", "multi_select": [ { "id": "??????????", "name": "GIMP", "color": "brown" } ] }, "リンク": { "id": "vQ%60%3F", "type": "url", "url": "https://juu7g.hatenablog.com/entry/blog/gimp/shukusho" }, "タイトル": { "id": "title", "type": "title", "title": [ { "type": "text", "text": { "content": "ブログに便利な画像の縮小、反転【GIMP】", "link": null }, "annotations": { "bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default" }, "plain_text": "ブログに便利な画像の縮小、反転【GIMP】", "href": null } ] } } } ], "next_cursor": null, "has_more": false, "type": "page", "page": {} }
先ほどプロパティ値の説明で使用した短い例で説明します。
id
や color
などはデータの追加や更新には不要なデータなので削除します。
▽整理する前のサンプル
"properties": { # JSONにはコメントを付けられないのでPythonで記述しています "カテゴリ": { # プロパティ名(キー) "id": "UNHI", # 不要 "type": "multi_select", # 型名 "multi_select": [ # 型に対する内容 { "id": "87ef771a-1e60-492a-b06a-2d8ed9dcd58d", # 不要 "name": "ブログ", "color": "brown" # 不要 }, { "id": "e869c74e-480b-43e4-a653-70f4f89406c4", # 不要 "name": "シニア", "color": "purple" # 不要 } ] },…
▽整理した結果のサンプル
"properties": { # JSONにはコメントを付けられないのでPythonで記述しています "カテゴリ": { # プロパティ名(キー) "type": "multi_select", # 型名 "multi_select": [ # 型に対する内容 { "name": "ブログ", }, { "name": "シニア", } ] },…
かなりスッキリします。
◇データ更新に必要なものだけにした結果
{ "object": "list", "results": [ { "properties": { "スター": { "number": 5 }, "掲載日": { "date": { "start": "2021-05-13T10:28:00.000+09:00", "end": null, "time_zone": null } }, "アイキャッチ画像": { "files": [ { "name": "https://cdn-ak.f.st-hatena.com/images/fotolife/??????????.png", "external": { "url": "https://cdn-ak.f.st-hatena.com/images/fotolife/??????????.png" } } ] }, "カスタムURL": { "rich_text": [ { "text": { "content": "blog/gimp/shukusho", "link": null } } ] }, "カテゴリ": { "multi_select": [ { "name": "ブログ" }, { "name": "シニア" } ] }, "タグ": { "multi_select": [ { "name": "GIMP" } ] }, "リンク": { "url": "https://juu7g.hatenablog.com/entry/blog/gimp/shukusho" }, "タイトル": { "title": [ { "text": { "content": "ブログに便利な画像の縮小、反転【GIMP】" } } ] } } } ], "next_cursor": null, "has_more": false }
◇Python でプロパティに変換
後はこのようなデータになるように、リテラルのところを変数に置き換えてデータ作成メソッドになるように修正します。
今回、更新用のデーは CSV ファイルを読み込んだ辞書型のデータを使います。
先ほどのデータの更新に不要な部分を取り除いた JSON データを基に Python の辞書型のデータを作ります。
いくつか注意点があります。
- CSV ファイルを読み込んだデータはすべて文字列なのでプロパティが数値型の場合には数値に変換が必要
- マルチセレクト用のデータはカンマ区切りの文字列(
"a,b"
)なので"name"をキーにした辞書のリスト([{"name":"a"}, {"name":"b"}]
)にする - タイムゾーンは動かないので日時に標準時との差を付加する
2022-07-10 15:30:41
⇒2022-07-10 15:30:41+09:00
- 設定値がない場合はキーごと削除する
◎コード
""" Notion用プロパティデータ作成 """ import re def set_properties(url:str="", title:str="", published:str="", updated:str="", bookmark:int=0, yellow:int=0, green:int=0, red:int=0, blue:int=0, purple:int=0, category:str="", eye_catch:str=""): """ 引数を値にしたNotionデータベースのプロパティ用辞書を作成する Args: any: get_hatena_infoで出力したCSVの各カラム Returns: dict: 特定Notionデータベースのプロパティ用辞書 """ # カスタマイズURLはURLのentryより後ろだけ c_url = re.sub("^.+/entry/", "", url) # CSVを読み込んだデータはすべて文字列なので数値は変換が必要 star_num = int(yellow) + int(green) + int(red) + int(blue) + int(purple) bookmark_num = int(bookmark) # マルチセレクト用のデータはカンマ区切りの文字列("a,b")なので"name"をキーにした辞書のリストにする c1 = [{"name":c} for c in category.split(",")] # t1 = [{"name":t} for t in tags] properties = { "スター": { "number": star_num }, "掲載日": { "date": { # タイムゾーンは動かないので日時に標準時との差を付加する "start": published+"+09:00", # "time_zone": "Asia/Tokyo" } }, "アイキャッチ画像": { "files": [ { "name": eye_catch, "external": { "url": eye_catch } } ] }, "ブックマーク": { "number": bookmark_num }, "カスタムURL": { "rich_text": [ { "text": { "content": c_url, } } ] }, "カテゴリ": { "multi_select": list(c1) }, # "タグ": { # "multi_select": list(t1) # }, "リンク": { "url": url }, "タイトル": { "title": [ { "text": { "content": title } } ] }, } # 設定がないキーは削除する if category == "": del properties["カテゴリ"] if eye_catch == "": del properties["アイキャッチ画像"] return properties
◆Python で実践
Python で Notion API を使ったプログラミングをしました。
データベースの更新や削除、情報取得やテストなどを作成したので紹介します。
全体のソースを見ると分かりますが、switch 変数を用意して処理を切り替えています。
説明するのは次の4つの処理です。
◇データベースの内容をJSONファイルに出力
Notion データベースを更新するプロパティ値を作るためにデータベースの中身を確認する必要がありました。
データベースオブジェクトの問い合わせの戻り値は辞書です。
辞書データを可視化するのによい方法を捜したところ、JSON のdump()メソッドが良いようです。
文字で JSON ファイルに出力されるので読めます。
▽呼び出し
doc = notion_api.get_database() # データベースを取得 notion_api.dump_results(doc) # JSONファイルに出力
▽データベースオブジェクトの問合せ
def get_database(self) -> dict: """ データベースを取得 Returns: dict: データベースの内容 """ try: my_page = self.notion.databases.query( **{ "database_id": self.DATABASE_ID, } ) except APIResponseError as error: # if error.code == APIErrorCode.ObjectNotFound: if error.code == APIErrorCode.ValidationError: # For example: handle by asking the user to select a different database print("データベースIDを確認してください") else: # Other error handling code print("インテグレーションのトークンを確認してください") # logging.exception(error.code) return my_page
▽JSON ファイルに出力
def dump_results(self, doc:dict): """ 辞書をjson形式のファイルに出力 Args: dict: 出力したい辞書 """ file_name = f"myDictionary_{datetime.now().strftime('%m%d')}.json" jf = open(file_name, "w", encoding="utf_8_sig") json.dump(doc, jf, ensure_ascii=False) jf.close()
◇データベースのデータ更新のテスト。辞書をリテラルで与えて更新
最終的には、CSV ファイルを読んでデータベースを更新します。
まずは、1件ずつ更新動作を確認するためにこちらの処理を用意しました。
「データベースのプロパティに合ったプロパティ値の作り方」で説明したデータベースを更新する時のプロパティ値を作成するメソッドを呼び出します。
引数には辞書型のデータを自分で用意します。
▽呼び出し
data = {"url":"https://xxx.hatenablog.com/entry/xxx", "title":"タイトル", "published":"2022-06-01 21:50:15", "yellow":37, "category":'シニア, 暮らし' } properties = notion_db_scm.set_properties(**data) # プロパティ用辞書作成 notion_api.append_page_2database(properties=properties) # 追加
▽データの追加
def append_page_2database(self, properties:dict): """ データベースに引数の内容を追加 Args: dict: 記事情報 Returns: dict: 操作の結果 """ try: my_page = self.notion.pages.create( **{ "parent":{"database_id": self.DATABASE_ID}, "properties":properties } ) except APIResponseError as error: if error.code == APIErrorCode.ObjectNotFound: # For example: handle by asking the user to select a different database print("データベースIDを確認してください") else: # Other error handling code print(f"target properties:{properties}") # logging.exception(error.code) return my_page
◇CSV ファイルを読んでデータベースを更新
読み込む CSV ファイルは次の記事のアプリで作成されるものです。
CSV ファイルのカラム構成は、次の記事で確認できます。
📄『はてなブログのスターとブックマークの数を取得するアプリ【フリー】🔗』
CSV ファイルは、DictReader() メソッドを使用して辞書型のデータに読み込みます。
そのデータからプロパティ用辞書を作成します。
データベースの対しての操作は、記事の URL がデータベースに存在するかどうかで追加するか更新するかを切り分けます。
▽呼び出し
if len(sys.argv) > 1: file_name = sys.argv[1] else: print(f"ファイルを指定してください") input("\n確認したらEnterキーを押してください") sys.exit() print(f"{file_name} の内容で更新します。") try: # CSV(1行目がカラム定義)を辞書として読んで with open(file_name, newline='', mode="r", encoding="utf-8-sig") as csvfile: spamreader = csv.DictReader(csvfile) for row in spamreader: properties = notion_db_scm.set_properties(**row) # プロパティ用辞書作成 # 更新データが既にデータベースにあるかをurlでチェック doc = notion_api.get_page_by_url(row.get("url")) # 問合せ(urlでフィルタリング) if doc: if len(doc["results"]) > 0: page_id = doc["results"][0].get("id") notion_api.update_page(page_id, properties) # 更新 print(f"更新:{row.get('title')}") else: notion_api.append_page_2database(properties) # 追加 print(f"追加:{row.get('title')}") else: # データベース読み込みに問題があったので中断 break print(f"処理終了") except Exception as e: print(f"エラーが発生しました:{e}")
▽データの問合せ(フィルタ指定)
def get_page_by_url(self, url:str) -> dict: """ データベースを取得 データベースの「リンク」プロパティを引数でフィルタリングした結果 Args: str: 記事のURL(データベースのキーとして扱う) Returns: dict: データベースの内容 """ my_page = None try: my_page = self.notion.databases.query( **{ "database_id": self.DATABASE_ID, "filter":{"or":[{ "property":"リンク", "url":{"equals":url} }]} } ) except APIResponseError as error: # if error.code == APIErrorCode.ObjectNotFound: if error.code == APIErrorCode.ValidationError: # For example: handle by asking the user to select a different database print("データベースIDを確認してください") else: # Other error handling code print("インテグレーションのトークンを確認してください") # logging.exception(error.code) return my_page
フィルタの指定は、データベースの「リンク」プロパティのプロパティ値を見て記述します。
"リンク": {"url": "https://juu7g.hatenablog.com/entry/blog/gimp/shukusho"},
とあるので、property
が「リンク」で、 url
が url 変数と等しい (equals) を指定します。
フィルタの指定は、or
を付ける必要はなかったと思います。
サンプルを基に作ったら、このようになってしまいました。
▽データの更新
def update_page(self, page_id:str, properties:dict) -> dict: """ データベースの既存のpage_idのデータに引数の内容を更新 Args: str: page ID dict: 記事情報 Returns: dict: 操作の結果 """ try: my_page = self.notion.pages.update( **{ "page_id":page_id, "properties":properties } ) except APIResponseError as error: if error.code == APIErrorCode.ObjectNotFound: # For example: handle by asking the user to select a different database print("データベースIDを確認してください") else: # Other error handling code # logging.exception(error.code) pass return my_page
◇データベースのデータ削除
削除処理は、まず、データベースに問合せして全ページオブジェクトを取得します。
データの削除に必要なページオブジェクトの ID を取得します。
ログ出力用にページオブジェクトの「タイトル」プロパティの値を取得します。
ID とタイトルを関連付けて処理を繰り返し全ページオブジェクトを削除します。
▽問い合わせの結果データの先頭
{ "object": "list", "results": [ { "object": "page", "id": "??????????",
問合せの結果は、results
キーの値が配列になり、ページオブジェクトが複数存在します。
ID はすぐ取れますが、タイトルはプロパティ値の中なのでオブジェクトが入れ子になっていて分かりにくいです。
▽呼び出し
doc = notion_api.get_database() # データベースを取得 if len(doc["results"]) > 0: page_ids = [obj["id"] for obj in doc["results"] if obj["object"] == "page"] # 結果からpage_idを取得 page_titles = [obj["properties"]["タイトル"]["title"][0]["text"]["content"] for obj in doc["results"] if obj["object"] == "page"] # 結果からタイトルを取得 for page_id, page_title in zip(page_ids, page_titles): notion_api.delete_block(page_id) # データベースから削除 print(f"削除:{page_title}")
▽削除処理
def delete_block(self, page_id:str) -> dict: """ データベースから引数のデータを削除 Args: str: page ID Returns: dict: 操作の結果 """ try: my_page = self.notion.blocks.delete( **{ "block_id":page_id } ) except APIResponseError as error: if error.code == APIErrorCode.ObjectNotFound: # For example: handle by asking the user to select a different database print("データベースIDを確認してください") else: # Other error handling code # logging.exception(error.code) pass return my_page
◇必要なパッケージ
- notion-client
【インストール】pip install notion-client
【インポート】 from notion_client import Client
◇全体のソース
全体のソースはこちらから取得できます。
取得先:GitHub juu7g/Python-use-Notion-API
◆Notion インテグレーションの作成とデータベース ID の取得
Notion API を使うためには Notion 側に準備が必要です。
必要なのは次の2つです。どちらも本記事で説明しているソースを使う場合は、環境変数に設定します。
- インテグレーションのトークン
- Notion データベースのデータベース ID
まず、Notion のインテグレーションを作成し、そのインテグレーションを介してアクセスしたいデータベースをシェアします。
イメージ的にはオンラインストレージ(インテグレーション)を作成してその中のファイル(データベース)をシェアするのに近いでしょうか。
◇インテグレーションの作成
- Notion API サイトへアクセス
(URL:https://developers.notion.com/) - ページ右上のリンク View my integrations をクリック
- 『私のインテグレーション | Notion開発者』が開く
- 「新しいインテグレーションを作成する」をクリック
- 新しいインテグレーション設定画面が表示されます
- 「名前」にインテグレーションの名前を入力
適当な名前を入力します - 「関連ワークスペース」を選択
個人使用の場合は一つしか選択肢がないと思います - 「機能」を選択
デフォルトの状態のままで大丈夫です
私は「ユーザー情報なし」にだけ変更しました - 「送信」をクリック
インテグレーションが作成されます - 「トークン」が表示されるのでコピー
- 表示をクリック
- コピーをクリック
こちらを環境変数に登録します
◇データベースをシェア
ここでのアクセスしたいデータベースというのは、「ブログ記事管理」データベースをコピーしたデータベースです。
- Notion のサイトでアクセスしたいデータベースを選択
- 画面右上の「共有」をクリック
- ダイアログが出るので「招待」をクリック
- インテグレーションの選択
選択肢から作成したインテグレーションを選択
選択後、再度「招待」をクリック
「編集権限」が表示されればOK - 「リンクをコピー」をクリック
データベースのURLがコピーされます - URL からデータベースIDを取得
(/
の次から?
の前まで)
コピーしたURLをどこかにペーストして実施
★データベースURL:https://www.notion.so/ここから~ここまで?v=ここにも値があります
⇒データベースID:ここから~ここまで
こちらを環境変数に登録します
◆環境変数の設定
本記事で説明しているソースを使って Notion データベースにアクセスするためには、環境変数に次のものを設定する必要があります。
環境変数の変数 | 値 |
---|---|
py_notion_int_token | Notion インテグレーショントークン |
py_notion_db | Notion データベース ID |
◇環境変数設定画面の起動
- スタートメニュー
- プログラムとファイルの検索に「環境変数」と入れる
- 検索結果に「環境変数を編集」が出るのでクリック
- 環境変数設定画面が出る
- 「新規」をクリック
- 変数名と変数値を入力してOKをクリックする
◆さいごに
Notion データベースを使い始めた時から Notion API は使ってみたいと思っていました。
いきなりではハードルが高そうに感じたので はてなフォトライフの API から始めました。
データベース更新用のデータを取得するために はてなブログの API も使いました。
そしてやっと Notion API を使うことができました。一歩一歩進んできたなと思います。
Notion API と notion-client の組合せは、仕様書を読み解くのが難しくて苦労しました。
特にプロパティ値の指定方法が理解できませんでした。
しかし、自分なりの理解しやすい方法を見つけてからは何とかなりました。
これから Notion API のプログラミングを始める方がこの記事で始めやすくなっていると幸いです。
📄 はてなブログのアイキャッチ画像のURLの取り方【Python】🔗
◇ご注意
本記事は次のバージョンの下で動作した内容を基に記述しています。
- Notion 2022年7月のNotionサービス
- Python 3.8.5
- notion-client 1.0.0
ご利用に際しては、『免責事項』をご確認ください。
お気づきの点がございましたら『お問い合わせ』からお問い合わせください。
◆参考
- Notion API:Notion API
- Notion リファレンス:Introduction
- データベースオブジェクト:Database object
- プロパティオブジェクト:Property object
- notion-client:notion-client · PyPI
- 解説:Notion APIでデータベースを操作する - Qiita
- 解説:Notion API × Python
- トークン解説:【Notion】APIついに実装...!簡単な動作確認をやってみる...!
- 日付解説:【Notion】Notion API 日付プロパティのtimezone設定について - Hanatare's PaPa