Flask Shorty:Flask + PostgreSQL で作る超軽量URL短縮サービス

App:https://flask-shorty.onrender.com/ ※1
App:https://pg-lab.ysnko.com/flask-shorty.cgi
GitHub:https://github.com/ynakao55/flask-shorty
※1 サービスが停止している場合は、起動に50秒程かかります。

Flask と PostgreSQL、Render を使ってURL短縮サービスを作成・公開しました。
この記事では、アプリの説明/学んだ技術/主要ファイル/Renderでのデプロイ要点をまとめます。
これ一つで、Webアプリ開発の基本要素(ルーティング、DB、テンプレート、環境変数、デプロイ)が一通り体験できます。


目次

アプリの説明

何をするアプリ?

入力された URL を 6文字コードで短縮し、/<code> にアクセスすると元URLへリダイレクトします。
トップページには直近で作成された短縮URLの一覧クリック数が表示され、削除ボタンで不要な短縮をDBから消せます。

主な機能

  • URL短縮(6文字の英数字コードを自動生成)
  • 既存URLの再利用(同じURLは重複作成しない)
  • 短縮URLへのアクセス数(clicks)のカウント
  • 最近作成した短縮一覧+削除ボタン(確認ダイアログ付き)
  • 基本的なバリデーション(http(s):// 付与・形式チェック)
  • 404/500 の簡易エラーページ
  • /health ヘルスチェック

技術スタック

  • Flask 3.x(ルーティング/テンプレート)
  • SQLAlchemy / Flask-SQLAlchemy(ORM)
  • PostgreSQL(RenderのマネージドDB)
  • Jinja2(テンプレート)
  • Bootstrap 5(UI)
  • gunicorn(本番サーバ)
  • python-dotenv(ローカル環境変数の読み込み)
  • validators(URLチェック)

学んだ技術とハマりどころ

1) ルーティングとフォーム処理

  • GET /:入力フォーム表示、最近の短縮リンク一覧
  • POST /shorten:短縮URL作成
  • GET /<code>:元URLへ302リダイレクト
  • POST /links/<id>/delete:DBから削除(今回追加)

2) DBモデリングとORM

  • Link テーブル
    id, original_url, short_code(unique), clicks, created_at
  • 重複URLは既存レコードを再利用して無駄な増殖を防止。
  • クリック数はアクセス時に UPDATE clicks = clicks + 1

3) 環境変数と接続文字列

  • Renderの DATABASE_URLpostgres:// 形式のことがあるため、SQLAlchemyで扱える postgresql://自動置換
  • さらにドライバ切り替え時は postgresql+psycopg:// を使う設計も視野に。

4) デプロイ時のPythonバージョンとDBドライバ

  • psycopg2-binaryPython 3.13 と相性問題が出やすい。
  • Python 3.10〜3.12 に固定し、psycopg2-binary==2.9.9 を使うと安定。
  • Render の EnvironmentPYTHON_VERSION を指定するとよい(例:3.10.11)。

主要なファイルの説明(抜粋)

flask-shorty/
  app.py                # ルート定義、DBモデル、短縮ロジック
  requirements.txt      # 依存パッケージ(Flask, SQLAlchemy, psycopg2-binary など)
  Procfile              # 本番起動コマンド(gunicorn)
  .env.example          # ローカル開発用の環境変数サンプル
  templates/
    base.html           # レイアウト
    index.html          # フォーム+最近の短縮URL一覧(削除ボタン付き)
    result.html         # 作成後の表示(コピー用UI)
    404.html / 500.html # 簡易エラーページ
  static/               # 必要ならCSS/JS/画像など

app.py の要点

  • Linkモデルshort_code に unique index)
  • コード生成secrets.choice で6文字を生成(衝突時はリトライ)
  • URL正規化:スキーム補完(example.comhttp://example.com
  • DB初期化:初回アクセス時に db.create_all()
  • 削除ルート

Render デプロイの要点(チェックリスト)

1) リポジトリ準備

  • requirements.txt
    • Flask / Flask-SQLAlchemy / SQLAlchemy
    • psycopg2-binary==2.9.9(Python 3.10〜3.12 推奨)
    • gunicorn / python-dotenv / validators
  • Procfileweb: gunicorn app:app
  • .env はコミットしない(.env.example は可)

2) Pythonバージョン固定

  • Render ダッシュボード → EnvironmentPYTHON_VERSION を追加(例:3.10.11

3) サービス作成

  • PostgreSQL(Mananged DB)を先に作成 → DATABASE_URL を取得
  • Web Service を「Create」→ リポジトリを選択
  • 環境変数
    • DATABASE_URL(Renderの値。postgres://はアプリ側で自動置換)
    • SECRET_KEY(本番用の十分長いランダム文字列)
    • APP_BASE_URL(任意。外部公開URLを固定したい場合)

4) ビルド&起動

  • Start は Procfile を自動検出(web: gunicorn app:app
  • DBマイグレーション不要(create_all() で自動作成)
  • うまくいかない時は Clear build cache → Manual deploy を実行

5) 動作確認

  • /でフォーム表示 → 短縮 → /<code> でリダイレクト確認
  • 一覧にクリック数が増えるか、削除が効くかチェック

スクリーンショット

トップページ(フォーム+一覧)

短縮結果画面(コピーUI)

404/500 ページ

伸びしろ(次の一手)

  • 認証(ログインユーザーだけ削除可能に)
  • 短縮コードのカスタムエイリアス
  • 有効期限の設定、パスワード付き短縮
  • API化/api/shorten)と簡単なフロントSPA
  • CI(テスト1本でもOK)&自動デプロイ

まとめ

  • 最小構成でも、DB連携→動くWeb→本番デプロイまで一気通貫で形にできたのが今回のポイント。
  • Render上のPythonバージョンとDBドライバは実務でもハマりやすい箇所で、ここを自力で突破できたのは強い実績になります。
  • 次は Rails / Django / Laravel でも同レベルのCRUDアプリを公開し、「複数フレームワークでデプロイまでやり切れる」ことを示していきます
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次