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?

Ajaxチャット / 投票(原理 : 星マーク) / タスク登録 / 画像upload/ モーダル表示

Last updated at Posted at 2025-05-03

チャット

python
from flask import Flask, render_template, request, jsonify
import time

app = Flask(__name__)

messages = []

@app.route('/')
def index():
    return render_template('chat.html')

@app.route('/send', methods=['POST'])
def send_message():
    message = request.form['message']
    messages.append(message)
    return jsonify({'message': message})

@app.route('/get_messages', methods=['GET'])
def get_messages():
    return jsonify({'messages': messages})
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>リアルタイムチャット</title>
    <script>
        function sendMessage() {
            const messageText = document.getElementById('message').value;
            if (messageText) {
                fetch('/send', {
                    method: 'POST',
                    body: new FormData(document.getElementById('messageForm'))
                })
                .then(response => response.json())
                .then(data => {
                    const message = data.message;
                    const newMessage = document.createElement('div');
                    newMessage.textContent = message;
                    document.getElementById('chatBox').appendChild(newMessage);
                    document.getElementById('message').value = '';  // フォームをリセット
                });
            }
        }

        function loadMessages() {
            fetch('/get_messages')
                .then(response => response.json())
                .then(data => {
                    const chatBox = document.getElementById('chatBox');
                    chatBox.innerHTML = '';
                    data.messages.forEach(message => {
                        const newMessage = document.createElement('div');
                        newMessage.textContent = message;
                        chatBox.appendChild(newMessage);
                    });
                });
        }

        setInterval(loadMessages, 2000);  // 2秒ごとに新しいメッセージを取得
    </script>
</head>
<body>

<h1>リアルタイムチャット</h1>

<div id="chatBox"></div>
<form id="messageForm" onsubmit="event.preventDefault(); sendMessage();">
    <textarea id="message" rows="4" cols="50"></textarea><br>
    <button type="submit">送信</button>
</form>

</body>
</html>

投票

python
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

votes = {'option1': 0, 'option2': 0, 'option3': 0}

@app.route('/')
def index():
    return render_template('vote.html', votes=votes)

@app.route('/vote', methods=['POST'])
def vote():
    option = request.form['option']
    if option in votes:
        votes[option] += 1
    return jsonify(votes)
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>投票システム</title>
    <script>
        function submitVote(option) {
            fetch('/vote', {
                method: 'POST',
                body: new URLSearchParams({'option': option})
            })
            .then(response => response.json())
            .then(data => {
                document.getElementById('voteResult').innerHTML = `
                    Option 1: ${data.option1} votes<br>
                    Option 2: ${data.option2} votes<br>
                    Option 3: ${data.option3} votes`;
            });
        }
    </script>
</head>
<body>

<h1>投票システム</h1>
<button onclick="submitVote('option1')">Option 1</button>
<button onclick="submitVote('option2')">Option 2</button>
<button onclick="submitVote('option3')">Option 3</button>

<h2 id="voteResult">
    Option 1: 0 votes<br>
    Option 2: 0 votes<br>
    Option 3: 0 votes
</h2>

</body>
</html>

画像アップロード

python
from flask import Flask, request, render_template, jsonify
import os

app = Flask(__name__)

UPLOAD_FOLDER = 'uploads/'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

@app.route("/mypage", methods=["GET", "POST"])
def mypage():
    if request.method == "POST":
        name = request.form["name"].strip()
        address = request.form["address"].strip()
        birthdate = request.form["birthdate"].strip()
        likes = request.form["likes"].strip()
        dislikes = request.form["dislikes"].strip()
        image_filename = request.form["image_filename"].strip()
        if name and address:
            db.session.add(Profile(name=name, address=address, birthdate=birthdate, likes=likes, dislikes=dislikes, image_filename=image_filename))
            db.session.commit()
        return redirect("/mypage")
    image_list = os.listdir(app.config['UPLOAD_FOLDER']) if os.path.exists(app.config['UPLOAD_FOLDER']) else []
    return render_template('mypage.html', username=current_user.username, image_list=image_list)

    
@app.route("/upload", methods=["POST"])
@login_required
def upload():
    if 'file' not in request.files:
        return jsonify({'error': 'ファイルが見つかりません'})
    file = request.files.get('file')
    if file: 
        filename = secure_filename(file.filename)
        file_path = os.path.join(upload_folder, filename)
        file.save(file_path)
        return jsonify({'filename': file.filename})
    else:
        return jsonify({'error': 'ファイルめよら'}), 400

@app.route('/uploads/<filename>')
@login_required
def uploaded_file(filename):
    return send_from_directory(app.config('UPLOAD_FOLDER'), filename)
html
<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>mypage</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</head>

<body class="bg-light">

    <!-- モーダル起動ボタン -->
    <button type="button" class="btn btn-primary mt-4" data-bs-toggle="modal" data-bs-target="#uploadModal">
        画像をアップロードする
    </button>

    <!-- モーダル -->
    <div class="modal fade" id="uploadModal" tabindex="-1" aria-labelledby="uploadModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <form id="uploadForm" enctype="multipart/form-data" onsubmit="event.preventDefault(); uploadImage();">
            <div class="modal-header">
              <h5 class="modal-title" id="uploadModalLabel">画像アップロード</h5>
              <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="閉じる"></button>
            </div>
            <div class="modal-body">
              <input type="file" name="file" class="form-control" onchange="previewImage(this)">
              <div id="preview" class="mt-2"></div>
            </div>
            <div class="modal-footer">
              <button type="submit" class="btn btn-success">アップロード</button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <!-- アップロードされた画像表示エリア -->
    <h4 class="mt-5">アップロード画像一覧</h4>
    <div id="imageDisplay" class="d-flex flex-wrap gap-3 mt-2"></div>

    <a href="{{ url_for('main.logout') }}" class="btn btn-danger mt-4">ログアウト</a>
</div>

<script>
function uploadImage() {
    const formData = new FormData(document.getElementById('uploadForm'));
    fetch('/upload', {
        method: 'POST',
        body: formData
    })
    .then(res => res.json())
    .then(data => {
        if (data.filename) {
            const img = document.createElement('img');
            img.src = '/uploads/' + data.filename;
            img.width = 200;
            img.classList.add("img-thumbnail");
            document.getElementById('imageDisplay').appendChild(img);

            // モーダルを閉じる
            const modal = bootstrap.Modal.getInstance(document.getElementById('uploadModal'));
            modal.hide();

            // プレビューも消す
            document.getElementById('preview').innerHTML = '';
        } else {
            alert(data.error || "アップロード失敗");
        }
    });
}

// プレビュー機能
function previewImage(input) {
    const preview = document.getElementById('preview');
    preview.innerHTML = '';
    if (input.files && input.files[0]) {
        const reader = new FileReader();
        reader.onload = function(e) {
            const img = document.createElement('img');
            img.src = e.target.result;
            img.width = 200;
            img.classList.add("img-preview", "img-thumbnail");
            preview.appendChild(img);
        }
        reader.readAsDataURL(input.files[0]);
    }
}
</script>

タスク追加 / 削除

python
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

tasks = []

@app.route('/')
def index():
    return render_template('tasks.html', tasks=tasks)

@app.route('/add-task', methods=['POST'])
def add_task():
    task = request.form['task']
    tasks.append(task)
    return jsonify({'task': task})

@app.route('/delete-task', methods=['POST'])
def delete_task():
    task = request.form['task']
    tasks.remove(task)
    return jsonify({'task': task})
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>タスク管理</title>
    <script>
        function addTask() {
            const taskText = document.getElementById('task').value;
            if (taskText) {
                fetch('/add-task', {
                    method: 'POST',
                    body: new URLSearchParams({'task': taskText})
                })
                .then(response => response.json())
                .then(data => {
                    const taskItem = document.createElement('li');
                    taskItem.textContent = data.task;
                    const deleteButton = document.createElement('button');
                    deleteButton.textContent = '削除';
                    deleteButton.onclick = function() {
                        deleteTask(data.task, taskItem);
                    };
                    taskItem.appendChild(deleteButton);
                    document.getElementById('taskList').appendChild(taskItem);
                    document.getElementById('task').value = '';  // フォームをリセット
                });
            }
        }

        function deleteTask(task, taskItem) {
            fetch('/delete-task', {
                method: 'POST',
                body: new URLSearchParams({'task': task})
            })
            .then(() => {
                taskItem.remove();
            });
        }
    </script>
</head>
<body>

<h1>タスク管理</h1>
<input type="text" id="task" placeholder="新しいタスク"><br>
<button onclick="addTask()">タスク追加</button>

<ul id="taskList">
    <!-- タスクはここに表示されます -->
</ul>

</body>
</html>

モーダル表示 やり方

<!-- JS入れる -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>


<!-- モーダル起動ボタン : data-bs-toggle="modal" -->
<button type="button" class="btn btn-primary mt-3" data-bs-toggle="modal" data-bs-target="#uploadModal">
    画像をアップロードする
</button>

<!-- 画像一覧表示 + 画像プレビュー表示 -->
<div class="modal fade" id="uploadModal" tabindex="-1" aria-labelledby="uploadModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <form id="uploadForm" enctype="multipart/form-data" onsubmit="event.preventDefault(); uploadImage();">
        <div class="modal-header">
          <h5 class="modal-title" id="uploadModalLabel">画像アップロード</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="閉じる"></button>
        </div>
        <div class="modal-body">
          <input type="file" name="file" class="form-control">
        </div>
        <div class="modal-footer">
          <button type="submit" class="btn btn-success">アップロード</button>
        </div>
      </form>
    </div>
  </div>
</div>

<!-- モーダル閉じる : bootstrap.Modal.getInstance -->
const modal = bootstrap.Modal.getInstance(document.getElementById('uploadModal'));
            modal.hide();

画像保存処理 理屈

画像カラム保存 + 画像保存ができてないと、保存できない
image_filename = request.form["image_filename"].strip()

def upload():
    if 'file' not in request.files:
        return jsonify({'error': 'ファイルが見つかりません'})
    file = request.files.get('file')
    if file: 
        filename = secure_filename(file.filename)
        file_path = os.path.join(upload_folder, filename)
        return jsonify({'filename': file.filename})
    else:
        return jsonify({'error': 'ファイルめよら'}), 400

    image_list = [p.name for p in Path(upload_folder).glob('*.*')]
    return render_template('mypage.html', username=current_user.username, images=image_list)

@main.route('/upload/<filename>')
@login_required
def uploaded_file(filename):
    return send_from_directory(current_app.config('UPLOAD_FOLDER'), filename)

非同期 仕組み

  mypage に画像選択ボタンモーダルあり
  
  JSでfetch(/upload, { method: "POST" })で 送信
  
  Flask側の /upload ルートが画像保存JSON返却
  
  JSがファイル名から <img src="/uploads/ファイル名"> をmypageに追加

ファイル表示

@app.route('/uploads/<filename>')
@login_required
def uploaded_file(filename):
    return send_from_directory(app.config('UPLOAD_FOLDER'), filename)
image_listでdata表示
<h4 class="mt-5">アップロード画像一覧</h4>
    <div id="imageDisplay" class="d-flex flex-wrap gap-3 mt-2"></div>
    {% for image in image_list %}
      <img src="{{ url_for('uploaded_file', filename=image) }}" width="200" class="img-thumbnail" alt="{{ image }}">
    {% endfor %}
</div>
アップロードされた画像のファイル名を取得し、それをリストに追加
image_list = os.listdir(app.config['UPLOAD_FOLDER']) if os.path.exists(app.config['UPLOAD_FOLDER']) else []

生年月日表示

html
<p>生年月日{{ birthdate.strftime('%Y年%m月%d日') }}</p>
ajax
<script>
  $('#showBirth').on('click', function () {
    const y = $('#year').val();
    const m = $('#month').val();
    const d = $('#date').val();

    if (y === "0" || m === "0" || d === "0") {
      alert("年月日をすべて選んでください。");
      return;
    }

    const dateStr = y + "年" + m + "月" + d + "日";
    $('#birthResult').text(dateStr);
    
    // モーダル表示
    const modal = new bootstrap.Modal(document.getElementById('birthModal'));
    modal.show();
  });
</script>
生年月日jsonデータを保存
from flask import Flask, request, jsonify
import json
import os

@app.route('/save_birth', methods=['POST'])
def save_birth():
    data = request.get_json()
    save_path = 'saved_birth.json'

    with open(save_path, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

    return jsonify({"message": "保存しました"})

画像を送る : POSt

 # お決まり文
 function uploadImage() {
    const formData = new FormData(document.getElementById('uploadForm'));
    fetch('/Flaskに書いてるURLへ', {
        method: 'POST',
        body: formData
    })
    .then(res => res.json())
    .then(data => {

# sample code
function uploadImage() {
    const formData = new FormData(document.getElementById('uploadForm'));
    fetch('/upload', {
        method: 'POST',
        body: formData
    })
    .then(res => res.json())
    .then(data => {
        if (data.filename) {
            const img = document.createElement('img');
            img.src = '/uploads/' + data.filename;
            img.width = 200;
            img.classList.add("img-thumbnail");
            document.getElementById('imageDisplay').appendChild(img);

Ajaxでリダイレクトさせる

html
<div id="index">
    {{ include "index.html" }}
</div>
<script>
    const index_url = {{ url_for("main.index")|tojson }}
    const index_div = getElementById("index")
    fetch(index_url)
        .then(response => response.text)
        .then(text => geology_div.innerHTML = text)
</script>

検索機能 ajax

ajax
$(document).on("keyup", "#search", function(e){
      var search = $('#search').val();
      if (search == ''){
        loaddata();
      }else{
        $("#load-table").html('');
        $.ajax({
          url : "searchdata",
          type : "POST",
          data : JSON.stringify({name : search}),
          dataType : "json",
          contentType : "application/json; charset=utf-8",
          success : function(data){
            if (data.status == false){
              $("#load-table").html('<tr><td colspan="6" align="center"><h3>No record found</h3></tr></td>');
            }else{
              $.each(data.data, function(key, value){
                $("#load-table").append('<tr>'+
                    '<td class="center">'+ value.sno +'</td>'+
                    '<td>'+ value.name +'</td>'+
                    '<td>'+ value.city +'</td>'+
                    '<td class="center"><button class="edit-btn" id="edit" data-id="'+ value.sno +'" data-name="'+ value.name +'" data-city="'+ value.city +'">Edit</button></td>'+
                    '<td class="center"><button class="delete-btn" id="delete" data-id="'+ value.sno +'">Delete</button></td>'+
                '</tr>');
              });
            }
          }
        });
      }
    });

  });

引用 : https://github.com/wpcodevo/flask-note-taking-api/blob/master/Note%20App.postman_collection.json

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?