チャット
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