feat: schema upgrade + import 159 books from reading list

- db.py: add group, isbn, priority, read_reason, read_order, cover_blob fields
- Import 159 books from booklist.md with group/priority/status metadata
- Include books.db in repo (personal use)
This commit is contained in:
kai
2026-03-25 14:55:23 +08:00
parent 8c8095d9ac
commit 69c34d4faf
5 changed files with 801 additions and 8 deletions
+38 -7
View File
@@ -14,6 +14,12 @@ def _connect():
return conn
def _column_exists(conn, table, column):
"""检查列是否已存在。"""
cols = conn.execute(f"PRAGMA table_info({table})").fetchall()
return any(c["name"] == column for c in cols)
def init_db():
"""初始化数据库和表结构。"""
conn = _connect()
@@ -39,6 +45,20 @@ def init_db():
updated_at TEXT DEFAULT (datetime('now', 'localtime'))
)
""")
# v2 新增字段 — 兼容已有数据库
new_cols = [
("\"group\"", "TEXT DEFAULT ''"),
("isbn", "TEXT DEFAULT ''"),
("priority", "TEXT DEFAULT ''"),
("read_reason", "TEXT DEFAULT ''"),
("read_order", "INTEGER"),
("cover_blob", "BLOB"),
("cover_local", "TEXT DEFAULT ''"),
]
for col_name, col_def in new_cols:
plain = col_name.strip('"')
if not _column_exists(conn, "books", plain):
conn.execute(f"ALTER TABLE books ADD COLUMN {col_name} {col_def}")
conn.commit()
conn.close()
@@ -46,17 +66,20 @@ def init_db():
def add_book(title, *, author=None, translator=None, publisher=None,
pub_date=None, cover_url=None, format="paper", status="to-read",
rating=None, douban_score=None, goodreads_score=None,
tags="", notes=None, start_date=None, finish_date=None):
tags="", notes=None, start_date=None, finish_date=None,
group="", isbn="", priority="", read_reason="", read_order=None):
"""添加一本书,返回新书 ID。"""
conn = _connect()
cur = conn.execute("""
INSERT INTO books (title, author, translator, publisher, pub_date,
cover_url, format, status, rating, douban_score,
goodreads_score, tags, notes, start_date, finish_date)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
goodreads_score, tags, notes, start_date, finish_date,
"group", isbn, priority, read_reason, read_order)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (title, author, translator, publisher, pub_date, cover_url,
format, status, rating, douban_score, goodreads_score,
tags, notes, start_date, finish_date))
tags, notes, start_date, finish_date,
group, isbn, priority, read_reason, read_order))
conn.commit()
book_id = cur.lastrowid
conn.close()
@@ -71,6 +94,8 @@ def update_book(book_id, **kwargs):
"title", "author", "translator", "publisher", "pub_date",
"cover_url", "format", "status", "rating", "douban_score",
"goodreads_score", "tags", "notes", "start_date", "finish_date",
"group", "isbn", "priority", "read_reason", "read_order",
"cover_blob", "cover_local",
}
fields = {k: v for k, v in kwargs.items() if k in allowed}
if not fields:
@@ -100,8 +125,8 @@ def get_book(book_id):
return dict(row) if row else None
def list_books(*, status=None, format=None, tag=None):
"""查询书目列表,支持按状态/格式/标签过滤。"""
def list_books(*, status=None, format=None, tag=None, group=None):
"""查询书目列表,支持按状态/格式/标签/分组过滤。"""
conn = _connect()
query = "SELECT * FROM books WHERE 1=1"
params = []
@@ -112,9 +137,11 @@ def list_books(*, status=None, format=None, tag=None):
query += " AND format = ?"
params.append(format)
if tag:
# 逗号分隔的 tags 字段中模糊匹配
query += " AND (',' || tags || ',' LIKE ?)"
params.append(f"%,{tag},%")
if group:
query += ' AND "group" = ?'
params.append(group)
query += " ORDER BY updated_at DESC"
rows = conn.execute(query, params).fetchall()
conn.close()
@@ -131,11 +158,15 @@ def get_stats():
by_format = {}
for row in conn.execute("SELECT format, COUNT(*) as cnt FROM books GROUP BY format"):
by_format[row["format"]] = row["cnt"]
by_group = {}
for row in conn.execute('SELECT "group", COUNT(*) as cnt FROM books WHERE "group" != "" GROUP BY "group"'):
by_group[row["group"]] = row["cnt"]
conn.close()
return {
"total": total,
"by_status": by_status,
"by_format": by_format,
"by_group": by_group,
}