【第2回】登山&キャンプ記録アプリ開発|投稿機能と画像アップロードを実装してみた!
こんにちは、Soraです!
前回はアプリの概要や技術スタックについて紹介しました。
今回は、実際に記録を投稿できるようにする「投稿機能」について紹介します!
写真のアップロードやGoogleマップの埋め込み、日付の取り扱いなど、初学者としてつまずいたポイントも含めて振り返ります。
✍️ 投稿機能でできること
- タイトル・日付・場所(住所)
- 感想の入力
- Google Map の埋め込み
- 写真の複数枚アップロード(1枚目は一覧に表示)
💡 使った機能とライブラリ
機能 | 使用技術/関数 |
---|---|
フォーム入力 | Flask / request.form |
日付変換 | datetime.strptime() |
写真の保存 |
uuid + secure_filename() + os.path.join()
|
複数枚アップ | request.files.getlist() |
画像の保存先 |
static/uploads/ フォルダ |
🔧 実装コード(抜粋)
@app.route('/create', methods=['GET', 'POST'])
@login_required
def create():
if request.method == 'POST':
title = request.form['title']
date_str = request.form['date']
date = datetime.strptime(date_str, "%Y-%m-%d").date() if date_str else None
address = request.form['address']
description = request.form['description']
map_iframe = request.form.get('map_iframe')
new_post = Post(
title=title,
date=date,
address=address,
description=description,
map_iframe=map_iframe,
user_id=current_user.id
)
db.session.add(new_post)
db.session.commit()
# 写真アップロード
if 'photos' in request.files:
photos = request.files.getlist('photos')
for photo in photos:
if photo and photo.filename != '':
filename = str(uuid.uuid4()) + "_" + secure_filename(photo.filename)
filepath = os.path.join('static/uploads', filename)
photo.save(filepath)
new_photo = Photo(post_id=new_post.id, photo_path=filename)
db.session.add(new_photo)
db.session.commit()
return redirect(url_for('home'))
return render_template('create.html')
😅つまずきポイントと解決法
- equest.form['date'] が文字列だった → datetime.strptime()で日付に変換
- 写真のファイル名がバラバラになる → uuidで一意な名前を生成
- request.files.getlist() で複数枚対応できることに気づくのが遅れた!
🛠 つまずきポイント①:フォームから取得した日付の扱い
Flaskでは request.form['date']
で取得した値は文字列(str)として渡ってくる。
しかし、SQLAlchemyで Date
型として保存するには、Pythonの date
オブジェクトである必要がある!
なので datetime.strptime()
を使って変換した👇
date = datetime.strptime(request.form['date'], "%Y-%m-%d").date()
🛠 つまずきポイント②:アップされた写真のファイル名
😭同じファイル名の写真がアップロードされたら上書きされる。
→✅ 解決法:uuid を使って一意な名前にする!
💡uuidとは?
絶対に重複しないIDを自動で作るための仕組み!
毎回ランダムでユニークなIDを作ってくれるから上書きの心配なし!
import uuid
from werkzeug.utils import secure_filename
filename = str(uuid.uuid4()) + "_" + secure_filename(photo.filename)
🛠 つまずきポイント③:複数枚の画像をアップロードしたい!
最初は request.files['photo']
で取得していたため、複数選択しても1枚目しか保存されませんでした。
調べてみると、Flaskでは request.files.getlist('photos')
を使うことで、複数の画像をリストで取得できると判明!
HTMLの <input>
に multiple
属性をつける必要もあります。
<input type="file" name="photos" multiple>
やってみた感想✨
- 写真を複数枚アップできるようにすると完成度が増した!
- 実際の運用を想定すると、保存先やファイル名の工夫が必要だと実感!
次回予告ッ‼️
次回は、投稿の詳細ページや編集・削除機能について紹介予定です!