news 2026/5/7 16:59:43

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/5/6 7:03:58

华为OD技术面真题 - 数据库MySQL - 2

文章目录 介绍一下MySQL查询语句执行过程简述一下MySQL的架构说一下你理解的数据库索引&#xff1f;分别说说索引的优点和缺点说说MySQL中索引类型&#xff1f;如何创建合适的索引&#xff1f;怎么优化查询速度 介绍一下MySQL查询语句执行过程 执行SQL查询语句会经过上述组件和…

作者头像 李华
网站建设 2026/5/5 18:27:45

自定义类型转换机制

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

作者头像 李华
网站建设 2026/5/6 3:24:10

Transformer 大模型架构深度解析(4)详解 Transformer 架构

目录 文章目录目录Transformer 架构Input EmbeddingPositional EncodingEncoder软对齐注意力的思想词向量相似度的计算方法Scaled Dot-Product AttentionSelf-AttentionMulti-Head Attention&#xff08;Self-Attention&#xff09;Feed Forward Neural NetworkResidual Connec…

作者头像 李华
网站建设 2026/5/7 16:39:40

‌别再手动对比日志了!AI日志分析工具实测TOP3

软件测试中的日志分析痛点‌ 在软件测试工作中&#xff0c;日志分析是核心环节&#xff0c;涉及错误追踪、性能监控和测试报告生成。传统手动方法耗时耗力&#xff1a;测试工程师需逐行比对日志文件&#xff0c;识别异常模式&#xff0c;平均每个项目消耗20-30小时。常见问题包…

作者头像 李华
网站建设 2026/4/30 21:29:43

基于Vue的数字图书馆设计与开发793m5(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末

系统程序文件列表 系统功能 用户,图书类别,图书信息 开题报告内容 一、 课题背景、研究目的与意义 1. 课题背景 随着信息技术的高速发展和数字化转型的深入推进&#xff0c;传统图书馆的服务模式面临诸多挑战&#xff1a;空间限制导致藏书容量有限&#xff0c;纸质资源易损…

作者头像 李华
网站建设 2026/5/7 4:58:59

基于spring boot的调查问卷系统的设计与实现(源码+论文+部署+安装)

感兴趣的可以先收藏起来&#xff0c;还有在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望可以帮到大家。一、程序背景在当前信息化快速发展的大环境下&#xff0c;传统纸质问卷调查存在效率低下、成本高昂、地域…

作者头像 李华