LoginSignup
1
1

More than 3 years have passed since last update.

Wiki.jsにSQLAlchemyで記事を作成してみた

Posted at

やってみたこと

多機能なWiki.jsですが、既存データの一括インポート方法がわからなかったので、無理やりデータベースを更新できるかやってみました。正式な方法ではないので、自己責任でお試しください。

※ データベースは、いろいろ選べますが、PostgreSQLを選びました。

手順

  • 準備
  • docker-composeでWiki.jsの起動
  • ローカルにSQLAlchemyの環境構築
  • データベースからクラス作成
  • SQLAlchemyで記事を作成

GIGAZINEの記事も参考にしてください。

準備

作業はmacOSのbashで確認しています。
docker-composeとPython3.8をインストールしておいてください。

docker-composeでWiki.jsの起動

Wiki.js - Docs」に起動方法がいろいろ書いてありますが、docker-composeを使います。
まずは、docker-compose.yamlを作成します。

bash
mkdir wikijs
cd wikijs
cat << EOF > docker-compose.yaml
version: "3"
services:

  db:
    image: postgres:11-alpine
    environment:
      POSTGRES_DB: wiki
      POSTGRES_PASSWORD: wikijsrocks
      POSTGRES_USER: wikijs
    ports:
      - "5432:5432"
    logging:
      driver: "none"
    restart: unless-stopped
    volumes:
      - db-data:/var/lib/postgresql/data

  wiki:
    image: requarks/wiki:2
    depends_on:
      - db
    environment:
      DB_TYPE: postgres
      DB_HOST: db
      DB_PORT: 5432
      DB_USER: wikijs
      DB_PASS: wikijsrocks
      DB_NAME: wiki
    restart: unless-stopped
    ports:
      - "80:3000"

volumes:
  db-data:
EOF

ローカル側のポート5432を変えた場合は、"5432:5432"を"15432:5432"のように変えて、以降の5432も変えてください。

起動&ログイン

docker-compose up -dでWiki.jsが起動します。なお、停止はdocker-compose downです。
http://localhost/でWiki.jsが利用できます。

ADMINISTRATOR ACCOUNTを適当に作成してください。そして作成したアカウントでログインしてください。

トップページ作成

ログイン直後は何もページがありません。まずは、トップページを作成します。
トップページのパスは、/<言語>/homeです。最初は、言語として英語(en)だけ使えます。

ここでは、言語として日本語(ja)を使うことにします。
まずは、英語のトップページを作成後、日本語の言語をインストールし、英語のトップページを削除して日本語のトップページを作成します。

+ CREATE HOME PAGE」を押してください。
「Markdown」を押して、「✓OK」を押して、「✓CREATE」を押してください。

トップページ(http://localhost/en/home)が開きます。Administratorでログインしているので、右上の「」で管理画面(http://localhost/a/dashboard)を開きます。

左側から「Locale」を選んでください。「Download Locale」から「Japanese」を選んで「雲に下矢印のマーク」の「Download」を押してください。そして、上に戻って「Locale Settings」を「Japanese」にし右上の「✓ APPLY」を押します。

アクティブな名前空間を日本語にしたので、トップページを日本語で作成し直しす必要があります。
左側から「ページ」を選んでください。Pathが「en/home」の項目を選び、「ACTIONS v」の「Delete」で削除します。

右上の「閉じる」で最初の画面に戻るので日本語のトップページを作成してください。

ローカルにSQLAlchemyの環境構築

Wiki.jsではブラウザで記事を作成できますが、ここではPythonからデータベースを直接編集して記事の作成を試みます。
まずは、Pythonの仮想環境を作成します。

bash
python3.8 -m venv venv
source venv/bin/activate
pip install psycopg2-binary SQLAlchemy

データベースからクラス作成

SQLAlchemyで使うクラスをデータベースから作成します。下記を実行するとdb_class.pyが作成されます。

bash
cat << EOF | python
import re

from sqlalchemy import MetaData, create_engine
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine("postgresql+psycopg2://wikijs:wikijsrocks@localhost:5432/wiki")

metadata = MetaData()
metadata.reflect(engine)

Base = declarative_base(metadata=metadata)


def _subfunc(m):
    s = ".".join(m.group(1).split(".")[-2:])
    return rf"ForeignKey('{s}')"


def make_class(cls):
    lst = [f"class {str(cls).split('.')[-1][:-2]}(Base):"]
    lst.append(f'    __tablename__ = "{cls.__tablename__}"\n')
    for column in cls.__table__.columns:
        s = repr(column)
        nam = s.split("'")[1]
        s = re.sub(r", table=[^>]+>", "", s)
        s = re.sub(r", server_default=[^)]+\)", "", s)
        s = re.sub(r"ForeignKey\('([^']+)'\)", _subfunc, s)
        lst.append(f"    {nam} = {s}")
    res = "\n".join(lst) + "\n"
    res = res.replace("metadata = Column", "metadata_ = Column")
    return res


def make_classes():
    lst = [
        """\
# made by make_classes
from typing import Any
from sqlalchemy import Column, ForeignKey, Text
from sqlalchemy.dialects.postgresql import (
    BOOLEAN, BYTEA, INTEGER, JSON, TEXT, TIMESTAMP, VARCHAR
)
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()  # type: Any
"""
    ]
    dc = {"__table_args__": {"autoload": True}}
    for tbl in sorted(metadata.tables):
        if tbl in {"brute"}:
            continue
        typ = type(tbl.title(), (Base,), dict(__tablename__=tbl, **dc))
        lst.append(make_class(typ))
    with open("db_class.py", "w") as fp:
        fp.write("\n".join(lst))


make_classes()
EOF

SQLAlchemyで記事を作成

まずは、ファイルを作成します。

bash
cat << EOF > main.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from db_class import *

engine = create_engine("postgresql+psycopg2://wikijs:wikijsrocks@localhost:5432/wiki")
Session = sessionmaker(bind=engine)
session = Session()
pgid = max(i.id for i in session.query(Pages).all()) + 1
ptid = max(i.id for i in session.query(Pagetree).all()) + 1
pg = Pages(
    id=pgid,
    path=f"test{pgid}",
    hash="0123456789001234567890abcdefghijklmnopqr",
    title=f"テストページ{pgid}",
    isPrivate=False,
    isPublished=True,
    content="",
    contentType="markdown",
    createdAt="2020-10-04T09:00:00.000Z",
    updatedAt="2020-10-04T09:00:00.000Z",
    editorKey="markdown",
    localeCode="ja",
    description="",
    authorId=1,
    creatorId=1,
    render="<div></div>",
    toc=[{"title": "", "anchor": "", "children": []}],
    extra={"js": "", "css": ""},
    publishStartDate="",
    publishEndDate="",
)
pt = Pagetree(
    id=ptid,
    path=pg.path,
    localeCode="ja",
    pageId=pgid,
    title=pg.title,
    depth=1,
    isPrivate=False,
    isFolder=False,
    ancestors=[],
)
session.add(pg)
session.add(pt)
session.commit()
session.close()
EOF

上記で、main.pyを作成します。
python main.pyで、テストページ...という空のページが作成されます。

内容は、Pages.contentPages.renderに記述します。contentに記述しただけだと表示されませんが、編集して保存すると表示されます。

バックアップ

pg_dump -h localhost -p 5432 -U wikijs wiki -f data.sqlでデータベースの内容をダンプできます。

psql -h ホスト -p 5432 -U ユーザ データベース -f data.sqlで空のPostgreSQLにデータを戻せます。

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1