[Flask]uuidを生成して専用URLを作成する
はじめに
PythonのWebアプリケーションフレームワークFlaskを使って、「消耗品買い物リスト」を作ってみるシリーズ第9回目です。
今回は、買い物リストページの基本部分と、トップページから買い物リストページを生成する機能を途中まで実装します。
前回まで
- 0回 : Flaskで簡単なWebサービスを作ってみる
- 1回 : スプレッドシート+Google Apps Scriptでプロトタイプを作る
- 2回 : FigmaでUI制作をしてみたが早々に次のフェーズに進んだ件
- 3回 : DockerでFlaskが動き、簡単なテストが通る状態を作る
- 4回 : [スクショ付き]AWSにVPCを構築し、EC2を立てる
- 5回 : EC2でDockerコンテナを起動し、Flaskを動かす
- 6回 : CircleCIでFlaskアプリの自動テストができるようにする
- 7回 : CircleCIでIP制限のあるEC2インスタンスに自動デプロイできるようにする
- 8回 : ユーザーストーリーマッピングで初期開発機能を洗い出す
今回やること
買い物リストの画面表示とリスト作成の原型を作ります。
機能概要 : 専用URLの発行
初期リリース段階ではログイン不要にしたいという理由から、買い物リストごとに専用URLを発行し、URLで直接アクセスできる仕様にします。
URLを知っていれば誰でも見られますし、URLを紛失した場合はアクセスできなくなります。
- 買い物リストを作成するとURLが発行される
- そのURLにアクセスすると買い物リストが閲覧・更新できる
という機能です。
専用URLをどうやって発行するか
URLは/page/XXX
(XXX部分がID)という構成にします。
ここで、発行時には、XXXとなるIDの部分がかぶらないように、一意にしておく必要があります。
色々と手法はあるものの、今回は定番かつ実装も楽なUUIDを採用します。
全体像
この機能の完成のためにざっとやることを書き出してみます。
- [ ] 買い物リスト新規作成
- [ ] 初期データの作成
- [ ] リストIDの作成(連番)
- [ ] UUIDの生成
- [ ] データを保存
- [ ] 初期データの作成
- [ ] 買い物リスト表示
- [ ] URLのuuidから対象データを検索・取得
- [ ] ページの表示
こんな感じですかね。
この記事では、まずは
– UUIDを生成して返す
– URLからUUIDを取得してページ表示
を実装します。
今回やらないこと
DBへのデータ保存はまだやりません。
URLからUUIDを取得してページ表示 : FlaskのRouting
あらためて。
まずは、/page/XXX
というURLが叩かれるとXXXの値を取得して表示できるようにします。
/page/XXX
でアクセスすると、- XXXと画面に記載されたページが表示される
Flaskで実現する方法を調べてみるとすぐにいいのが見つかりました。
Quickstart — Flask Documentation (1.1.x)
より抜粋
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % escape(username)
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# show the subpath after /path/
return 'Subpath %s' % escape(subpath)
もうこれをやればOKですね。
uuidを生成する : uuid.uuid4()
新しいページを生成するために、uuidを生成します。
生成には、Pythonにあるライブラリをそのまま使います。
実装が楽で助かる…
import uuid as _uuid
# uuid生成
uuid = str(_uuid.uuid4())
二行で済みました。(uuid4()はuuid型を返すのでstr型に変換してます)
以下の記事は処理の中身まで追っていて勉強になります。
[Python] UUIDを生成するuuid.uuid4()はどうやってUUIDを生成しているのか? | Developers.IO
サンプル
こんなコードにしました。
ロジック部分
app.py
メイン処理。/page/XXX
でアクセスされるとshow_user_pageメソッドを呼び出します。
from flask import Flask, render_template, request, redirect, url_for
from markupsafe import escape
import uuid as _uuid
from classes import page as pg
app = Flask(__name__)
@app.route('/')
def index():
title = "to buy list"
return render_template('index.html', title=title)
@app.route('/page/<uuid>/')
def show_user_page(uuid):
title = 'Your page'
# show user_page from uuid
uuid = '%s' % escape(uuid)
page = select_page_info(uuid)
return render_template('user_page.html', title=title, page=page)
def select_page_info(uuid):
"""uuidから対象ページのデータを取得
Return:
Page : ページクラスのインスタンス
"""
page = pg.Page(uuid)
return page
@app.route('/page/create')
def create_new_page():
"""新規ページを作成する
"""
# uuid生成
uuid = str(_uuid.uuid4())
# レコード生成
# ページ表示
return show_user_page(uuid)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
classes/page.py
class Page:
def __init__(self, uuid):
self.uuid = uuid
ページ表示部分
template/application.html
基盤となるページです。
<!DOCTYPE html>
<html>
<head>
<title>{{ title }} | tobuylist</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0">
</head>
<body>
<div>
{% block body %}
{% endblock %}
</div>
</body>
</html>
template/user_page.html
リスト表示用のページです。
ロジック部分で受け取ったuuidをそのまま表示する、極めて単純な処理です。
{% extends "application.html" %}
{% block body %}
<div>
<h1>{{ title }}</h1>
<div>
My id is {{ page.uuid }}.
</div>
</div>
{% endblock %}
template/index.html
トップページです。
Create pageというリンクで専用URLを発行します。
{% extends "application.html" %}
{% block body %}
<div>
<h1>トップページ</h1>
<div class="field">
<a href='page/create'>Create new page</a>
</div>
</div>
{% endblock %}
挙動
買い物リスト画面表示
Flaskを立ち上げて、/page/hogehoge
にアクセスしてみます。
hogehogeという文字列を表示できました。
買い物リスト生成
トップページからCreate page
リンクをクリックしてみます。
↓
uuidが生成され、それが画面内に表示されました。
気になる点
トップページからはCreate pageすると、URLがpage/create
のままなので、page/XXX
となるように後々手を加えたいと思います。
最後に
画面表示の原型ができたので、さらにデータ保存や読み込みの機能を組み込んでいきます。
ディスカッション
コメント一覧
まだ、コメントがありません