0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【第2回】登山&キャンプ記録アプリ開発|投稿機能と画像アップロードを実装してみた!

Posted at

【第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')

😅つまずきポイントと解決法

  1. equest.form['date'] が文字列だった → datetime.strptime()で日付に変換
  2. 写真のファイル名がバラバラになる → uuidで一意な名前を生成
  3. 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>

やってみた感想✨

  • 写真を複数枚アップできるようにすると完成度が増した!
  • 実際の運用を想定すると、保存先やファイル名の工夫が必要だと実感!

次回予告ッ‼️

次回は、投稿の詳細ページや編集・削除機能について紹介予定です!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?