news 2026/8/16 11:45:20

Python Flask:登录版利率计算器实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python Flask:登录版利率计算器实战

目录

一、技术栈说明(轻量易部署)

二、环境准备

三、完整代码实现

1. 后端主文件 app.py

2. 前端模板文件夹及文件

(1)登录页面 login.html

(2)计算器页面 calculator.html

四、代码核心部分解释

1. 登录验证逻辑

2. Web 版计算逻辑

3. 前端页面设计

五、运行与使用步骤

六、扩展建议(可选)

总结


基于 Python Flask 框架的带登录功能的 Web 版利率计算器,支持通过浏览器访问、登录验证,登录后可输入本金、利率、计息期数,选择单利 / 复利计算并实时显示结果。以下是完整的实现方案,包含前端页面(登录页 + 计算器页)和后端逻辑,代码可直接运行,适合新手部署和使用。

一、技术栈说明(轻量易部署)

  • 后端:Python + Flask(轻量级 Web 框架,无需复杂配置,新手友好)
  • 前端:HTML + 简单 CSS(无需前端框架,页面简洁易用)
  • 登录验证:基于 Flask Session 的简单用户名密码验证(演示用,可扩展为数据库存储)
  • 核心功能:复用单利 / 复利计算逻辑,适配 Web 表单提交

二、环境准备

首先安装 Flask 依赖(打开终端 / 命令行执行):

pip install flask

三、完整代码实现

创建一个文件夹(如interest_calculator),在其中新建 2 个文件:

1. 后端主文件app.py

python

运行

from flask import Flask, render_template, request, session, redirect, url_for, flash import math # 初始化Flask应用 app = Flask(__name__) # 配置Session密钥(必须,用于登录状态保存) app.secret_key = "interest_calc_2026_secure_key" # 实际使用可替换为随机字符串 # 内置测试用户(演示用,实际可替换为数据库查询) VALID_USERS = { "admin": "123456", "user1": "user123" } # 登录验证装饰器(保护计算器页面,未登录则跳转到登录页) def login_required(f): def wrapper(*args, **kwargs): if "username" not in session: flash("请先登录后再使用计算器!", "warning") return redirect(url_for("login")) return f(*args, **kwargs) wrapper.__name__ = f.__name__ return wrapper # 利率计算核心函数 def calculate_interest(principal, rate, periods, interest_type="simple"): """ 计算单利/复利的利息和本息和 :param principal: 本金(元) :param rate: 年利率(百分比,如5表示5%) :param periods: 计息期数(年) :param interest_type: 计息方式(simple=单利,compound=复利) :return: 利息(保留2位小数)、本息和(保留2位小数) """ rate = rate / 100 # 转换为小数 if interest_type == "simple": total = principal * (1 + rate * periods) else: total = principal * math.pow((1 + rate), periods) interest = total - principal return round(interest, 2), round(total, 2) # 路由1:登录页面(GET请求显示页面,POST请求验证登录) @app.route("/login", methods=["GET", "POST"]) def login(): # 如果已登录,直接跳转到计算器页面 if "username" in session: return redirect(url_for("calculator")) if request.method == "POST": username = request.form.get("username") password = request.form.get("password") # 验证用户名密码 if username in VALID_USERS and VALID_USERS[username] == password: session["username"] = username # 保存登录状态到Session flash(f"登录成功!欢迎 {username}", "success") return redirect(url_for("calculator")) else: flash("用户名或密码错误,请重新输入!", "danger") # GET请求显示登录页面 return render_template("login.html") # 路由2:计算器页面(需登录才能访问) @app.route("/calculator", methods=["GET", "POST"]) @login_required def calculator(): result = None # 存储计算结果 if request.method == "POST": try: # 获取表单输入 principal = float(request.form.get("principal")) rate = float(request.form.get("rate")) periods = int(request.form.get("periods")) interest_type = request.form.get("interest_type") # 校验输入合法性 if principal <= 0: flash("本金金额必须大于0!", "danger") elif rate < 0 or rate > 100: flash("年利率需在0-100之间(如5表示5%)!", "danger") elif periods <= 0: flash("计息期数必须大于0!", "danger") else: # 计算利息 interest, total = calculate_interest(principal, rate, periods, interest_type) # 组装结果数据 result = { "principal": round(principal, 2), "rate": rate * 100, # 转回百分比显示 "periods": periods, "interest_type": "单利" if interest_type == "simple" else "复利", "interest": interest, "total": total } flash("计算成功!", "success") except ValueError: flash("输入错误!请输入有效的数字!", "danger") # 渲染计算器页面,传递登录用户名和计算结果 return render_template("calculator.html", username=session["username"], result=result) # 路由3:退出登录 @app.route("/logout") @login_required def logout(): session.pop("username", None) # 清除登录状态 flash("已成功退出登录!", "success") return redirect(url_for("login")) # 路由4:首页(重定向到登录页) @app.route("/") def index(): return redirect(url_for("login")) # 启动应用 if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=5000)

2. 前端模板文件夹及文件

interest_calculator文件夹下新建templates子文件夹,再在其中创建 2 个 HTML 文件:

(1)登录页面login.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>利率计算器 - 登录</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: Arial, sans-serif; } body { background-color: #f5f5f5; display: flex; justify-content: center; align-items: center; min-height: 100vh; } .login-box { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); width: 400px; } .login-box h2 { text-align: center; margin-bottom: 20px; color: #333; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; color: #666; } .form-group input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; } .btn { width: 100%; padding: 10px; background-color: #007bff; color: white; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; } .btn:hover { background-color: #0056b3; } .alert { padding: 10px; margin-bottom: 15px; border-radius: 4px; font-size: 14px; } .alert-danger { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; } </style> </head> <body> <div class="login-box"> <h2>利率计算器 - 用户登录</h2> <!-- 显示提示信息 --> {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} <div class="alert alert-{{ category }}">{{ message }}</div> {% endfor %} {% endif %} {% endwith %} <!-- 登录表单 --> <form method="POST"> <div class="form-group"> <label for="username">用户名</label> <input type="text" id="username" name="username" required placeholder="请输入用户名(测试:admin)"> </div> <div class="form-group"> <label for="password">密码</label> <input type="password" id="password" name="password" required placeholder="请输入密码(测试:123456)"> </div> <button type="submit" class="btn">登录</button> </form> </div> </body> </html>
(2)计算器页面calculator.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>利率计算器 - 主页</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: Arial, sans-serif; } body { background-color: #f5f5f5; padding: 20px; } .container { max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .header h2 { color: #333; } .header a { color: #dc3545; text-decoration: none; font-size: 14px; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; color: #666; } .form-group input, .form-group select { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; } .btn { padding: 10px 20px; background-color: #007bff; color: white; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; } .btn:hover { background-color: #0056b3; } .alert { padding: 10px; margin-bottom: 15px; border-radius: 4px; font-size: 14px; } .alert-success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; } .alert-danger { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; } .alert-warning { background-color: #fff3cd; color: #856404; border: 1px solid #ffeeba; } .result { margin-top: 20px; padding: 20px; background-color: #e9f7fe; border-radius: 4px; display: none; } .result.show { display: block; } .result h3 { margin-bottom: 10px; color: #333; } .result p { margin: 5px 0; font-size: 16px; color: #666; } .result p span { font-weight: bold; color: #007bff; } </style> </head> <body> <div class="container"> <div class="header"> <h2>欢迎 {{ username }} | 利率计算器</h2> <a href="/logout">退出登录</a> </div> <!-- 显示提示信息 --> {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} <div class="alert alert-{{ category }}">{{ message }}</div> {% endfor %} {% endif %} {% endwith %} <!-- 计算器表单 --> <form method="POST"> <div class="form-group"> <label for="principal">本金金额(元)</label> <input type="number" id="principal" name="principal" step="0.01" required placeholder="请输入大于0的金额,如10000.00"> </div> <div class="form-group"> <label for="rate">年利率(%)</label> <input type="number" id="rate" name="rate" step="0.01" required placeholder="请输入0-100之间的数值,如4.5"> </div> <div class="form-group"> <label for="periods">计息期数(年)</label> <input type="number" id="periods" name="periods" min="1" required placeholder="请输入大于0的整数,如3"> </div> <div class="form-group"> <label for="interest_type">计息方式</label> <select id="interest_type" name="interest_type" required> <option value="simple">单利</option> <option value="compound">复利</option> </select> </div> <button type="submit" class="btn">计算</button> </form> <!-- 计算结果展示 --> {% if result %} <div class="result show"> <h3>计算结果</h3> <p>本金:<span>{{ result.principal }}</span> 元</p> <p>年利率:<span>{{ result.rate }}</span> %</p> <p>计息期数:<span>{{ result.periods }}</span> 年</p> <p>计息方式:<span>{{ result.interest_type }}</span></p> <p>到期利息:<span>{{ result.interest }}</span> 元</p> <p>到期本息和:<span>{{ result.total }}</span> 元</p> </div> {% endif %} </div> </body> </html>

四、代码核心部分解释

1. 登录验证逻辑

  • Flask Session保存登录状态,login_required装饰器确保未登录用户无法访问计算器页面;
  • 内置测试用户(admin/123456user1/user123),实际使用可替换为数据库(如 SQLite/MySQL)查询;
  • 登录失败 / 成功通过flash提示用户,提升交互体验。

2. Web 版计算逻辑

  • 复用之前的单利 / 复利计算函数,适配 Web 表单的 POST 提交方式;
  • 前端表单添加required属性强制输入,后端额外校验数值合法性(如本金 > 0、利率 0-100);
  • 计算结果通过模板变量传递到前端,格式化显示(保留 2 位小数)。

3. 前端页面设计

  • 登录页 / 计算器页均做了简单样式优化,适配浏览器显示;
  • 提示信息分类展示(成功 / 危险 / 警告),结果区域仅在计算后显示,界面更整洁。

五、运行与使用步骤

  1. 确保文件结构正确:

plaintext

interest_calculator/ ├── app.py └── templates/ ├── login.html └── calculator.html
  1. 运行app.py(终端执行):
python app.py
  1. 打开浏览器,访问http://localhost:5000(或http://你的IP:5000,局域网内其他设备也可访问);
  2. 登录:输入测试用户名admin,密码123456,点击 “登录”;
  3. 使用计算器:输入本金(如 10000)、年利率(如 4.5)、期数(如 3),选择计息方式,点击 “计算”,即可看到结果。

六、扩展建议(可选)

  1. 持久化用户:将用户信息存入 SQLite/MySQL 数据库,替代内置字典;
  2. 记住登录状态:添加 “记住我” 功能,延长 Session 有效期;
  3. 更多计息方式:支持按月 / 按日计息,增加 “计息周期” 选择项;
  4. 数据导出:将计算结果导出为 Excel/CSV 文件;
  5. 样式优化:使用 Bootstrap 框架美化页面,适配手机端。

总结

  1. 核心功能:实现了浏览器登录验证 + 利率计算,支持单利 / 复利,输入合法性校验,结果清晰展示;
  2. 易用性:基于 Flask 的轻量级架构,代码结构清晰,新手可快速部署和修改;
  3. 扩展性:预留了扩展接口(如数据库、更多计息方式),可根据需求升级。

整个应用无需复杂的服务器配置,本地运行即可满足个人 / 小团队使用,完全适配 “浏览器登录 + 利率计算” 的核心需求。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/30 13:03:58

C++中的工厂模式实战

1、非修改序列算法这些算法不会改变它们所操作的容器中的元素。1.1 find 和 find_iffind(begin, end, value)&#xff1a;查找第一个等于 value 的元素&#xff0c;返回迭代器&#xff08;未找到返回 end&#xff09;。find_if(begin, end, predicate)&#xff1a;查找第一个满…

作者头像 李华
网站建设 2026/8/7 21:35:43

Claude Code的完美平替:OpenCode #x2B; GitHub Copilot

引言&#xff1a;Claude 虽好&#xff0c;但你真的能用上吗&#xff1f; 在当前席卷全球的“Vibe Coding”浪潮中&#xff0c;Anthropic 推出的 Claude 系列模型 终端工具 Claude Code&#xff0c;凭借极强的逻辑推理能力&#xff0c;成为了开发者眼中的“白月光”。但现实是残…

作者头像 李华
网站建设 2026/8/7 21:36:11

TestOps实战:如何让测试不再“事后补救”

打破“救火队长”的恶性循环 在高速迭代的DevOps环境中&#xff0c;测试团队常陷入“上线-故障-紧急修复”的被动局面。传统“事后补救”模式不仅消耗30%以上的研发资源处理缺陷&#xff0c;更导致用户信任流失与市场机会错失。TestOps通过文化变革与技术重构&#xff0c;将测…

作者头像 李华
网站建设 2026/7/31 7:41:00

浮点数在内存中的存储

一 国际标准根据国际标准IEEE754&#xff0c;任意的二进制浮点数可以表示为一下的形式&#xff1a;二 存储方式1.32位的浮点数&#xff0c;最高一位存储符号位S&#xff0c;接着8位存储指数E&#xff0c;剩下的23位存储有效数字M&#xff1b;2.对于64位的浮点数&#xff0c;最…

作者头像 李华
网站建设 2026/8/7 10:17:42

计算机毕业设计项目源码/Flask+vue的博客系统设计与实现附开题报告,毕业论文,毕设代码

博主介绍&#xff1a; CSDN毕设辅导第一人、靠谱第一人、csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客优秀创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;…

作者头像 李华