TL;DR
下のサイトをつくった。
https://nepris.herokuapp.com/
Githubリポジトリはこちら。
https://github.com/glyzinieh/nepris
備忘録を兼ねて、開発の経緯をご紹介します。
はじめに
当方初心者のため、至らぬ点があればアドバイスをよろしくお願いいたします。お気軽にコメントください。
それでははじめにネップリ共有サイト NePriS のご紹介をさせていただきます。
そもそも「ネップリ」って?
「ネップリ」とは、セブンイレブン・ファミリーマート・ローソンなどのコンビニエンスストアで提供されている「 ネットプリント 」のことを指します。ネットプリントでは、自分で作成・撮影した画像作品を各サービスのアプリやサイトに登録することで予約番号が発行され、それをコンビニにあるマルチコピー機に入力することで、登録した画像をプリントアウトすることができます。
ネットプリントの予約番号を共有することで、様々な作品をプリントアウトすることができるわけです。
この予約番号の共有には、一般的にTwitterなどのSNSが用いられていますが、ネップリの 共有 ・ 検索 ・ 宣伝 のためのポータルを目指して開発されているのがネップリ共有サイト「 NePriS (ネプリス)」です。
基本方針
- 0円 で運用
- サーバーは Heroku
- 無料で使えるため
- サーバーサイドは Flask を使う
- 過去に触れたことがあったため
- DBは Googleスプレッドシート を利用
- HerokuのDBは、学生のためクレジットカードが使えないので✕
- GUIで触れて便利だから
- 画像データは 自宅鯖 (Synology NAS)に保存
- 自宅鯖で 自作API を実行し、書き込み・読み込みができるようにする
開発
実際に作業を進める上での ポイント や 躓いた点 を残します。
HTML
レスポンシブ対応 のためにBootstrap5
を利用します。初めて触ったので分からないことだらけでした。
navbar
解説サイトを読んでも、なぜか想定通りに動きませんでした。
結局、公式ドキュメントをコピペして解決しました。
nav_link
に、active
クラスとaria-current="page"
属性を動的に与える方法を悩んだが、Javascript
とJinja2
を使いゴリ押しで解決しました。
登録ページ
方針でも示した通り、データはGoogleスプレッドシート、画像データは自宅鯖に送信します。
予約番号
pattern
属性で文字種・文字数を制限した上で、Javascript
で強制的に大文字入力になるように設定します。
初期状態では、両方にrequired
属性を設定し、一方が入力されたら他方のrequired
属性を解除することで、「どちらか必須」のバリデーションを実現しました。
validation
Bootstrap5
のvalidation
仕様がよく分からなかったが、調べてみるとどうやらJavascript
のform.checkValidity()
関数で適切か判定し、表示しているらしい。
Javascript
が分かってないとダメですね…
ということで公式ドキュメントのコピペで解決しました。
Javascript
で対象の要素に対してsetCustomValidity("エラー名")
を実行すると、独自でエラー状態にできる。解除するときはsetCustomValidity("")
の様に空文字を与える。
データベース
gspread
のget_all_records()
を使うと'00000
が00000
になってしまう等不都合があるため、get_all_values()
で取得した リストのリスト を 辞書のリスト に変換する自作メソッドをgspread.Worksheet
クラスに追加しました。
Githubでget_all_records()
のコードを確認したところ、同様の実装をしていたので恐らく問題は無いと思います。
登録処理
id
は連番で1
ずつ加算されるように実装しました。
Jinja2
でstatus
変数によって表示を変えることで、サンクスページにエラー文等を表示できるようにしました。
画像
拡張子ではなく、送信されたMIME-type
で判断しています。
読み込み速度を改善するために、BytesIO
を使ってpillow
でwebp
形式に変換してから保存します。
作品ページ
自宅鯖上の画像を、BytesIO
を使って、send_file
で返します。
画像
CSSで以下を設定することで、画像の縦横比を保ったまま、画像のサイズを変えています。
img {
aspect-ratio: 4 / 3;
object-fit: contain;
}
利用規約・プライバシーポリシー
正直全く分からん!
個人情報に当たる情報を収集することになりそうなので掲載します。
これで正しいのか分かりません。
法律家とかに相談してみたいけれど、金欠なのでね……
一応、良いウェブサービスを支える 「利用規約」の作り方がとても参考になりました。
sitemap.xml
Flaskの拡張機能にFlask-Sitemapなるものがあったのでこれを利用して生成します。
日本語の情報が無いに等しく若干苦労しました。
こちらが参考になりました。
サービス名決定
こちらのサイトを参考にさせていただきました。
商標とかが若干心配ですが、問題ないことを信じます。
ロゴ
デザインセンスが皆無のため、友人に依頼しました。ありがたい!
Google Search Console
サイトをGoogleの検索エンジンに登録するために必要です。
仕様が謎です。何回かリクエストを送信しているが、登録されているのか分かりません。
おわりに
初めてWebサービスの個人開発をして、技術不足を痛感しました。
とりあえずJavascript
を学びたいです。
運営者ギルドの皆様に様々なアドバイスを頂きました。この場を借りて御礼申し上げます。ありがとうございました。
追記
アクセス数が思うように伸びなかったため、Herokuの有料化をきっかけに休止中です。
おまけ
開発中に思ったことなどを残しておきます。読み飛ばしていただいて構いません。
VSCodeは余計なモジュールをimportするな
エディターにVisualStudioCodeを利用していて、自動でモジュールをimport
してくれる機能は便利だが、たまに全く関係ないモジュールが追加されていて、エラーが発生して焦ることがあった。
結局、gitのDiffで余計なモジュールがimport
されていることに気が付き、事なきを得た。
VSCodeの全角文字
全角文字に対してエラーが出るのは嬉しいが、わざと使ってるのもあるからどうにかしてほしい。
Mermaid
この記事で初めて使った。直感的でいいですね。
Bootstrap Icons
フォントで使えるから便利。
型は大事
型を間違っていてエラーが出た。モジュールを使っていると原因が掴みづらい。
型アノテーションを活用したりして正しい変数を与えると分かりやすくなる。