家の本棚スペースが限られているため、年末の大掃除であまり読まなくなった本をダンボールに詰めようと考えました。
ただ、何も考えずに詰めると、どの箱に何の本があるか分からなくなります。
そこで、今年さわった技術を使って、ダンボールに入れた本を管理するDjangoアプリ danborary
を作りました*1。
目次
環境
- mac / Windows
- Python 3.8
- Django 3.1.4
- Django REST framework 3.12.2
- django-datatables-view 1.19.1
- reportlab 3.5.56
- pyndlsearch 1.0
- jQuery 3.5.1
- Bootstrap 4.5.2
機能概要
- ダンボールに管理用バーコードを貼り付けるため、印刷用バーコードラベルをpdf形式で作成する
- 書籍のISBNを元に、国立国会図書館サーチの検索APIを使い、タイトルなどを取得する
- ダンボールの管理用バーコードと書籍のISBNを紐付けて、SQLiteへ保存する
- ダンボールに詰めた本は、jQuery Datatablesによりグリッドで表示する
- できる限り、バーコードの読み取りだけで保存までできるUIにする
機能詳細
ラベル印刷
印刷用バーコードラベルで使うバーコード形式は、
- 手元にあるバーコードスキャナが1次元しか対応していない
- ダンボールの量はそんなに多くない
ことから、Code39としました。
Djangoアプリでpdfを作成する方法は以前やった方法を流用します。
Django + ReportLabをHerokuで動かしてpdfを表示する - メモ的な思考的な
印刷用ラベルは、A-oneの品番 28923
を使い、A4サイズに1片70mm×42.3mmのシールとして用意します。
[ 28923:ラベルシール[インクジェット] ] - 商品情報|ラベル・シールのエーワン
以下の記事を参考に、ラベルの中心あたりに印字するように調整します。
PDFをpythonで生成してみる
また、ラベルをなくしてしまっても再生成できるよう、URLで開始番号を指定します (http://localhost:8000/packing/print/start/<開始番号>/
)。
できたものはこんな感じです。
メニュー
印刷と箱詰めを切り替えられるよう、メインメニューを用意します。
箱詰め画面
BootstrapとjQuery Datatablesを使った画面です。
一番上の検索欄に書籍のISBNを読み込ませると、国立国会図書館の検索APIへリクエストし、書籍データを画面に反映します。
なお、検索APIを短期間で多数使うと問題があるかもしれないので、強制的に1秒くらい time.sleep させています。
また、同じISBNを読み込んだ場合は、検索APIを使わずにデータベースの内容を取得するようにしています。
あとは、巻数を入力して登録します。
- 手元に1から始まるバーコードを用意しておけば、バーコードを読み込ませるだけで済む
- 箱詰めする書籍はそんなに多くない
と考えて、自分で入力する形としました。
登録するとこんな感じになります。
作らなかった機能
年末の大掃除前についカッとなって作ったDjangoアプリであり、以前からあたためていたものではありません。
そのため、「年末の大掃除」という絶対の納期を守らないといけないことから、いくつかの機能を省いています。
削除機能
DB自体を消せばいいし、ということで削除機能は用意しませんでした。
所有している本の管理機能
本を管理するには本自体にもバーコードを貼る必要がありそうでした。
ただ、今回は「ダンボールに入れた本を管理する」という目的だったので、工数がかかりそうなこの機能は不要と考えました。
技術的なところ
国立国会図書館の検索API用ライブラリについて
APIの仕様書を見ると、いくつか用意されているインタフェースのレスポンスは、いずれもXML形式のようでした。
API仕様の概要 « 国立国会図書館サーチについて
そこでラッパーライブラリがないかを探してみたところ、 pyndlsearch
があったため、使うことにしました。
https://github.com/nocotan/pyndlsearch
DjangoアプリのView
今回はグリッド表示でjQuery Datatablesを使うことから、その部分のViewは django-datatables-view
で実装しました。
https://bitbucket.org/pigletto/django-datatables-view/
一方、今後 jQueryから別のライブラリに移行するかもしれないことを考え、他の部分はDjango REST frameworkのViewで実装し、アプリも分けておきました。