You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flask网页中实现按钮点击后状态永久保存?

Hey there! Let's fix that persistent button state issue for your CS50 final project. Right now, you're only updating the button's look client-side—when you refresh, there's no server-side data to pull the saved state from. Here's a step-by-step solution to make those statuses stick using your Flask/SQL setup:

1. First, Set Up a Database Table to Track Statuses

You'll need a table to store each user's application status per firm and role type. Run this SQL query to create it (assuming you already have a users table for authenticated users and firm_names has an id primary key):

CREATE TABLE application_status (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    firm_id INTEGER NOT NULL,
    application_type TEXT NOT NULL, -- Matches your button names: spring, asset, ib, etc.
    status INTEGER NOT NULL DEFAULT 0, -- 0 = Not started, 1 = In progress, 2 = Applied
    FOREIGN KEY(user_id) REFERENCES users(id),
    FOREIGN KEY(firm_id) REFERENCES firm_names(id),
    UNIQUE(user_id, firm_id, application_type) -- Prevent duplicate entries for the same user/firm/role
);

2. Modify Your Flask Route to Fetch Saved Statuses

Update the /summertable route to pull existing statuses for the logged-in user and pass them to the template:

@app.route("/summertable")
@login_required
def summertable():
    # Get firms + their saved statuses for the current user (use LEFT JOIN to include firms with no status yet)
    firms = db.execute("""
        SELECT fn.id, fn.firm_name,
               COALESCE(spring.status, 0) AS spring_status,
               COALESCE(asset.status, 0) AS asset_status,
               COALESCE(ib.status, 0) AS ib_status,
               COALESCE(risk.status, 0) AS risk_status,
               COALESCE(markets.status, 0) AS markets_status
        FROM firm_names fn
        LEFT JOIN application_status spring 
            ON fn.id = spring.firm_id 
            AND spring.user_id = ? 
            AND spring.application_type = 'spring'
        LEFT JOIN application_status asset 
            ON fn.id = asset.firm_id 
            AND asset.user_id = ? 
            AND asset.application_type = 'asset'
        LEFT JOIN application_status ib 
            ON fn.id = ib.firm_id 
            AND ib.user_id = ? 
            AND ib.application_type = 'ib'
        LEFT JOIN application_status risk 
            ON fn.id = risk.firm_id 
            AND risk.user_id = ? 
            AND risk.application_type = 'risk'
        LEFT JOIN application_status markets 
            ON fn.id = markets.firm_id 
            AND markets.user_id = ? 
            AND markets.application_type = 'markets'
    """, (session["user_id"],) * 5)

    # Map status codes to human-readable text and colors for easy template use
    status_map = {
        0: {"text": "Not started", "color": ""},
        1: {"text": "In progress...", "color": "LightSalmon"},
        2: {"text": "Applied", "color": "PaleGreen"}
    }

    return render_template("table.html", firms=firms, status_map=status_map)

3. Update the HTML Template to Render Saved States

Modify your table buttons to load the initial status from the database, and add data attributes to pass firm/role info to JavaScript:

{% extends "layout.html" %}
{% block title %} Application Tracker {% endblock %}
{% block main %}
<table class="table-striped tracker" style="table-align" id="tracker">
  <tr>
    <th style="text-align:left">Firms</th>
    <th>Spring weeks</th>
    <th>Asset management</th>
    <th>Investment banking</th>
    <th>Risk</th>
    <th>Global Markets</th>
  </tr>
  {% for firm in firms %}
  <tr>
    <td>{{ firm.firm_name }}</td>
    <!-- Spring Weeks Button -->
    <td>
      <button 
        onclick="updateStatus(this)" 
        type="button" 
        class="btn button" 
        data-firm-id="{{ firm.id }}"
        data-type="spring"
        data-current-status="{{ firm.spring_status }}"
        style="background-color: {{ status_map[firm.spring_status].color }}">
        {{ status_map[firm.spring_status].text }}
      </button>
    </td>
    <!-- Asset Management Button -->
    <td>
      <button 
        onclick="updateStatus(this)" 
        type="button" 
        class="btn button" 
        data-firm-id="{{ firm.id }}"
        data-type="asset"
        data-current-status="{{ firm.asset_status }}"
        style="background-color: {{ status_map[firm.asset_status].color }}">
        {{ status_map[firm.asset_status].text }}
      </button>
    </td>
    <!-- Investment Banking Button -->
    <td>
      <button 
        onclick="updateStatus(this)" 
        type="button" 
        class="btn button" 
        data-firm-id="{{ firm.id }}"
        data-type="ib"
        data-current-status="{{ firm.ib_status }}"
        style="background-color: {{ status_map[firm.ib_status].color }}">
        {{ status_map[firm.ib_status].text }}
      </button>
    </td>
    <!-- Risk Button -->
    <td>
      <button 
        onclick="updateStatus(this)" 
        type="button" 
        class="btn button" 
        data-firm-id="{{ firm.id }}"
        data-type="risk"
        data-current-status="{{ firm.risk_status }}"
        style="background-color: {{ status_map[firm.risk_status].color }}">
        {{ status_map[firm.risk_status].text }}
      </button>
    </td>
    <!-- Global Markets Button -->
    <td>
      <button 
        onclick="updateStatus(this)" 
        type="button" 
        class="btn button" 
        data-firm-id="{{ firm.id }}"
        data-type="markets"
        data-current-status="{{ firm.markets_status }}"
        style="background-color: {{ status_map[firm.markets_status].color }}">
        {{ status_map[firm.markets_status].text }}
      </button>
    </td>
  </tr>
  {% endfor %}
</table>

<script>
// Match the status mapping from your Flask route
const statusMap = {
  0: { text: "Not started", color: "" },
  1: { text: "In progress...", color: "LightSalmon" },
  2: { text: "Applied", color: "PaleGreen" }
};

async function updateStatus(button) {
  let currentStatus = parseInt(button.dataset.currentStatus);
  // Cycle through statuses: 0 →1 →2 →0
  let nextStatus = (currentStatus + 1) % 3;

  // Update button UI immediately for better user experience
  button.textContent = statusMap[nextStatus].text;
  button.style.backgroundColor = statusMap[nextStatus].color;
  button.dataset.currentStatus = nextStatus;

  // Send update to server to save in database
  try {
    const response = await fetch("/update_status", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-CSRFToken": "{{ csrf_token() }}" // Include this if you use Flask-WTF for CSRF protection
      },
      body: JSON.stringify({
        firm_id: button.dataset.firmId,
        type: button.dataset.type,
        status: nextStatus
      })
    });

    if (!response.ok) {
      // Revert button if server update fails
      button.textContent = statusMap[currentStatus].text;
      button.style.backgroundColor = statusMap[currentStatus].color;
      button.dataset.currentStatus = currentStatus;
      alert("Failed to save status. Please try again.");
    }
  } catch (error) {
    // Revert button on network error
    button.textContent = statusMap[currentStatus].text;
    button.style.backgroundColor = statusMap[currentStatus].color;
    button.dataset.currentStatus = currentStatus;
    alert("Network error. Please check your connection.");
  }
}
</script>
{% endblock %}

4. Add a Flask Route to Handle Status Updates

Create a POST route to save the new status to the database (use INSERT OR REPLACE to create or update entries):

from flask import request, jsonify

@app.route("/update_status", methods=["POST"])
@login_required
def update_status():
    data = request.get_json()
    firm_id = data.get("firm_id")
    app_type = data.get("type")
    status = data.get("status")

    # Validate input
    if not firm_id or not app_type or status is None:
        return jsonify({"success": False, "message": "Missing required data"}), 400

    # Insert or replace the status entry for the user/firm/role
    db.execute("""
        INSERT OR REPLACE INTO application_status (user_id, firm_id, application_type, status)
        VALUES (?, ?, ?, ?)
    """, (session["user_id"], firm_id, app_type, status))
    db.commit()

    return jsonify({"success": True})

Quick Notes to Keep in Mind

  • Make sure your firm_names table has an id primary key (if it doesn't, add it with ALTER TABLE firm_names ADD COLUMN id INTEGER PRIMARY KEY AUTOINCREMENT;).
  • If you're not using Flask-WTF for CSRF protection, you can skip the X-CSRFToken header, but it's recommended to add CSRF safeguards for production.
  • Test by clicking a button, refreshing the page—your status should now persist!

内容的提问来源于stack exchange,提问作者tobywinn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 18:47:48