Python + Flask 做个接口-员工带薪年假查询
zhezhongyun 2025-08-06 23:59 38 浏览
学Python有一段时间了,但接口还没去做过。也就是前端html,css,javascripts,后端就用Python。
先看效果图:
安装Python 和Flask这些我跳过,自行安装。
总体目录结构:
app.py代码如下:
一:导入必要的python库,记的要有app = Flask(__name__)
from flask import Flask, render_template, jsonify, request
import pyodbc
from datetime import datetime as dt
import pandas as pd
app = Flask(__name__)
二:先配置连接到后端数据库的连接信息
# 定义数据库连接信息
server = '0.0.0.0\sql2008' #IP地址
database = 'XXXX' # 数据库名
username = 'sa'
password = ''
# 连接Microsoft SQL Server数据库
try:
conn = pyodbc.connect('DRIVER={SQL Server};SERVER=' + server + ';DATABASE=' + database + ';UID=' + username + ';PWD=' + password)
print('数据库连接成功!')
except Exception as e:
print('数据库连接失败'+e)
conn.close()
三:从数据库中获取数据的接口
# 按钮“查询”的触发函数
@app.route('/api/data', methods=['GET'])
def get_data():
as_year = request.args.get('as_year')
as_empid = request.args.get('as_empid')
# print(as_year + as_empid)
if as_year and as_empid:
data = onclick(as_year, as_empid)
return jsonify(data)
else:
return jsonify({"error": "Missing as_year or as_empid parameters"}), 400
def onclick(as_year,as_empid):
"显示查询年假表格数据"
# 表查询语句 中文显示会乱码的要convert 成navrchar(12)类型
ls_year = as_year
today = str(dt.today().date())
# print(today)
Enddate = dt.strptime(ls_year + '-12-31', "%Y-%m-%d")
Empid = as_empid
sql_cmd = (f"SELECT emp_id as 工号 from 表名" where 条件)
data = pd.read_sql(sql_cmd, conn)
# print(data)
return data.to_dict(orient='records')
四:最后给flask配置一个主页的路由。
# API路由
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
五:index.html 代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>年度带薪年假查询</title>
<script src="
https://cdn.tailwindcss.com"></script>
<link href="
https://cdn.jsdelivr.net/npm/font-awesome@
4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3874c8',
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.fixed-bottom-right {
position: fixed;
right: 1rem;
bottom: 1rem;
}
.header-height {
height: 50px;
}
.table-shadow {
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
}
}
</style>
</head>
<body class="bg-gray-50 min-h-screen flex flex-col">
<!-- 头部 -->
<header class="bg-primary header-height text-white flex items-center justify-between px-4 shadow-lg z-10">
<h1 class="text-xl font-bold">年度带薪年假查询</h1>
<button id="menu-toggle" class="p-2 rounded-full hover:bg-primary-700 transition-colors">
<i class="fa fa-bars text-xl"></i>
</button>
</header>
<!-- 主内容区 -->
<main class="flex-1 p-4 md:p-6">
<!-- 查询条件区域 -->
<div class="bg-white rounded-lg shadow-md p-4 mb-4">
<h2 class="text-lg font-semibold mb-4 text-gray-700">查询条件</h2>
<div class="flex flex-col md:flex-row gap-4">
<div class="flex-1">
<label for="as_year" class="block text-sm font-medium text-gray-700 mb-1">输入年度</label>
<input type="text" id="as_year" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary transition">
</div>
<div class="flex-1">
<label for="as_empid" class="block text-sm font-medium text-gray-700 mb-1">请输入工号</label>
<input type="text" id="as_empid" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary transition">
</div>
<div class="flex items-end">
<button id="query-btn" class="w-full md:w-auto bg-primary hover:bg-primary/90 text-white font-medium py-2 px-4 rounded-md transition duration-300 transform hover:scale-[1.02] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary">
<i class="fa fa-search mr-2"></i>查询
</button>
</div>
</div>
</div>
<!-- 结果展示区域 -->
<div class="bg-white rounded-lg shadow-md p-4">
<h2 class="text-lg font-semibold mb-4 text-gray-700">查询结果</h2>
<!-- 加载状态 -->
<div id="loading" class="hidden flex justify-center items-center py-16">
<div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-primary"></div>
</div>
<!-- 表格容器 -->
<div id="table-container" class="hidden overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 table-shadow">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">工号</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">姓名</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">入职日期</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">雇佣状态</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">可休时数</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">工龄</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">己休时数</th>
</tr>
</thead>
<tbody id="result-body" class="bg-white divide-y divide-gray-200">
<!-- 结果将在这里动态生成 -->
</tbody>
</table>
<!-- 分页控件 -->
<div id="pagination" class="flex items-center justify-between px-4 py-3 sm:px-6 mt-4">
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700">
显示第 <span id="page-range" class="font-medium">1-2</span> 条,共 <span id="total-count" class="font-medium">2</span> 条
</p>
</div>
<div>
<nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
<a href="#" class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
<span class="sr-only">上一页</span>
<i class="fa fa-chevron-left"></i>
</a>
<a href="#" class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-primary text-sm font-medium text-white hover:bg-primary/90">
1
</a>
<a href="#" class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
2
</a>
<span class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700">
...
</span>
<a href="#" class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
4
</a>
<a href="#" class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
<span class="sr-only">下一页</span>
<i class="fa fa-chevron-right"></i>
</a>
</nav>
</div>
</div>
</div>
</div>
<!-- 空状态 -->
<div id="empty-state" class="hidden flex flex-col items-center justify-center py-16">
<i class="fa fa-search text-6xl text-gray-300 mb-4"></i>
<p class="text-gray-500">请输入查询条件并点击查询按钮</p>
</div>
<!-- 错误状态 -->
<div id="error-state" class="hidden bg-red-50 border-l-4 border-red-400 p-4 my-4">
<div class="flex">
<div class="flex-shrink-0">
<i class="fa fa-exclamation-triangle text-red-500"></i>
</div>
<div class="ml-3">
<p id="error-message" class="text-sm text-red-700"></p>
</div>
</div>
</div>
<!-- 无结果状态 -->
<div id="no-result" class="hidden flex flex-col items-center justify-center py-16">
<i class="fa fa-folder-open-o text-6xl text-gray-300 mb-4"></i>
<p class="text-gray-500">没有找到匹配的记录</p>
</div>
</div>
</main>
<!-- 页脚 -->
<footer class="bg-white border-t border-gray-200 py-4 px-6">
<div class="text-center text-gray-500 text-sm">
<span id="footer-text"></span>
</div>
</footer>
<!-- 侧边栏 -->
<div id="right-drawer" class="fixed inset-y-0 right-0 w-64 bg-white shadow-lg transform translate-x-full transition-transform duration-300 ease-in-out z-20 lg:hidden">
<div class="p-4">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold text-gray-700">菜单</h3>
<button id="close-drawer" class="p-1 rounded-full hover:bg-gray-100 transition-colors">
<i class="fa fa-times"></i>
</button>
</div>
<nav class="space-y-2">
<a href="#" class="block px-4 py-2 rounded-md text-base font-medium text-gray-700 hover:bg-gray-50">首页</a>
<a href="#" class="block px-4 py-2 rounded-md text-base font-medium text-gray-700 hover:bg-gray-50">报表管理</a>
<a href="#" class="block px-4 py-2 rounded-md text-base font-medium text-gray-700 hover:bg-gray-50">员工管理</a>
<a href="#" class="block px-4 py-2 rounded-md text-base font-medium text-gray-700 hover:bg-gray-50">系统设置</a>
</nav>
</div>
</div>
<!-- 遮罩层 -->
<div id="overlay" class="fixed inset-0 bg-black bg-opacity-50 z-10 hidden transition-opacity duration-300"></div>
<script>
// 侧边栏控制
const menuToggle = document.getElementById('menu-toggle');
const rightDrawer = document.getElementById('right-drawer');
const closeDrawer = document.getElementById('close-drawer');
const overlay = document.getElementById('overlay');
menuToggle.addEventListener('click', () => {
rightDrawer.classList.toggle('translate-x-full');
overlay.classList.toggle('hidden');
document.body.classList.toggle('overflow-hidden');
});
closeDrawer.addEventListener('click', () => {
rightDrawer.classList.add('translate-x-full');
overlay.classList.add('hidden');
document.body.classList.remove('overflow-hidden');
});
overlay.addEventListener('click', () => {
rightDrawer.classList.add('translate-x-full');
overlay.classList.add('hidden');
document.body.classList.remove('overflow-hidden');
});
// 设置页脚日期
document.getElementById('footer-text').textContent = new Date().getFullYear();
// 显示空状态
document.getElementById('empty-state').classList.remove('hidden');
document.getElementById('table-container').classList.add('hidden');
document.getElementById('error-state').classList.add('hidden');
document.getElementById('no-result').classList.add('hidden');
// 查询按钮点击事件
document.getElementById('query-btn').addEventListener('click', async function() {
// 获取输入值
const as_year = document.getElementById('as_year').value.trim();
const as_empid = document.getElementById('as_empid').value.trim();
// 简单验证
if (!as_year) {
showError('请输入年度');
return;
}
if (!as_empid) {
showError('请输入工号');
return;
}
// 显示加载状态
document.getElementById('empty-state').classList.add('hidden');
document.getElementById('table-container').classList.add('hidden');
document.getElementById('error-state').classList.add('hidden');
document.getElementById('no-result').classList.add('hidden');
document.getElementById('loading').classList.remove('hidden');
try {
// 调用真实的 API
await fetchApiData(as_year, as_empid);
} catch (error) {
showError(error.message);
} finally {
// 隐藏加载状态
document.getElementById('loading').classList.add('hidden');
}
});
// 调用真实的 API
async function fetchApiData(year, empId) {
const apiUrl = `
http://192.168.0.41:5000/api/data?as_year=${year}&as_empid=${empId}`;
try {
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// 清空表格内容
const resultBody = document.getElementById('result-body');
resultBody.innerHTML = '';
// 如果有数据,填充表格
if (data.length > 0) {
data.forEach(item => {
const row = document.createElement('tr');
row.className = 'hover:bg-gray-50 transition';
row.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item['工号']}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item['姓名']}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item['入职日期']}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item['雇佣状态']}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item['可休时数']}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item['工龄']}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item['己休时数']}</td>
`;
resultBody.appendChild(row);
});
// 显示表格
document.getElementById('table-container').classList.remove('hidden');
// 更新分页信息
document.getElementById('page-range').textContent = `1-${data.length}`;
document.getElementById('total-count').textContent = data.length;
} else {
// 显示无结果状态
document.getElementById('no-result').classList.remove('hidden');
}
} catch (error) {
throw error;
}
}
// 显示错误信息
function showError(message) {
document.getElementById('error-message').textContent = message;
document.getElementById('error-state').classList.remove('hidden');
}
</script>
</body>
</html>
六:启动后端服务器
出现这样表示成功了,
七:浏览器上输入http://192.168.0.41:5000 或 http://127.0.0.1:5000 ,就可以了。
#python自学# #pythonflask##flask框架有什么用#
相关推荐
- VSCode中值得推荐的常用的23个高效前端插件(工具篇)(一)
-
VSCode是我们前端开发的一个强大的IDE,所以选择趁手好用的插件是提高开发效率,然后剩下的时间用来摸鱼是很有必要滴。工具篇(23)Chinese(Simplified)vscode我们都知道是...
- 高级前端进阶,用gulp提升你的开发效率
-
前言:这两天动手配置了一下gulp,发现gulp配置简单,构建速度快,在某些使用场景下还是个不错的选择,本文从零开始构建,到最后打包发布到生成环境。通过本文可以快速上手gulp,文末附送github源...
- Chrome 110 3大新特性!CSS支持画中画!
-
大家好,很高兴又见面了,我是"前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天带着大家一起看看最新发布的Chrome1...
- 用html中If语句——判断ie浏览器的版本
-
if语句的代码的语法非常简单,,就是一个if判断语句来判断浏览器的类型和版本,应用类似<!--[iflteIE6]>和<![endif]-->语法结构包孕起来...
- 谷歌浏览器怎么开启无痕浏览_谷歌浏览器怎么开启无痕浏览模式
-
很多用户在使用谷歌浏览器时,不希望留下任何上痕迹,开启无痕浏览器是最好的选择。这个模式下可以更好的保护个人隐私记录,给你带来更加安全的冲浪体验,接下来就给大家详细介绍下谷歌浏览器的无痕浏览模式,希望对...
- Linux命令那么多,其实只需要记住这些就足够了!
-
你好,这里是网络技术联盟站,我是瑞哥。Linux命令行是一个强大且灵活的工具,可以极大地提高用户的工作效率和系统管理能力。我们都知道,Linux命令非常多,但是在实际的工作中,日常使用到的命令并不多,...
- Linux如何查看文件_linux如何查看文件大小
-
Linux如何查看目录下的所有文件?用ls(list)查看当前目录下的所有文件和子目录。Ls查看目录下的文件,怎么区分是目录还是文件呢?第一种方式,我们可以通过颜色来区分目录和文件。默认情况下,目录显...
- Linux系统man命令使用详解_linux man命令详解
-
man命令是在Linux和Unix系统上用于查看系统手册页(manualpages)的工具。手册页提供了关于系统命令、函数和文件的详细文档。命令语法:man[选项][命令或主题]参数:[选项]...
- linux ps命令详解_linux中ps
-
linux中ps只显示进程的静态快照,及瞬间的进程状态,它拥有众多的风格,可分为3组:UNIX风格,BSD风格,GNU风格,本文介绍UNIX风格的ps指令。参数ps[-aefFly][-ppid...
- 如何在 Linux 上查找系统硬件信息?hwinfo命令很强大!
-
hwinfo是一个功能强大的硬件信息查询工具,专为Linux系统设计。它能够提供系统中几乎所有硬件组件的详细信息,包括但不限于CPU、内存、硬盘、网络设备、USB设备、显卡、声卡等。与其他常...
- Linux Shell 入门教程(二):常用命令大全与使用技巧
-
在上一节《理解Linux与Shell》中,我们了解了Linux是什么、Shell是什么以及常见的Shell类型。这一篇,我们将正式动手操作,掌握使用频率最高、最实用的Linux命令...
- SpringBoot应用部署神器:可视化服务管理脚本让运维更轻松
-
在SpringBoot应用的生产环境部署中,传统的手动启停服务方式不仅效率低下,还容易出错。今天分享一个功能强大的可视化服务管理脚本,让SpringBoot应用的部署和运维变得简单高效。痛点分析:传统...
- 一次虚拟机性能问题导致的应用故障
-
最近我负责维护的一套语音平台出了问题。故障现象据客户反馈是转入IVR以后没有正常响应,客户无奈挂机了。老实说,刚开始接到用户反馈的时候,我是不太相信的。我们的系统平时运行运行很稳定,客户的并发数不大,...
- linux中的常用命令_linux常用命令及含义
-
linux中的常用命令linux中的命令统称shell命令shell是一个命令行解释器,将用户命令解析为操作系统所能理解的指令,实现用户与操作系统的交互shell终端:我们平时输入命令,执行程序的那个...
- linux学习笔记——常用命令-文件处理命令
-
ls目录处理命令:ls全名:list命令路径:/bin/ls执行权限:所有用户ls–ala--alll–long-i查看i节点ls–i查看i节点命令名称:mkdir命令英文原意:m...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)
- HTML button formtarget 属性 (30)
- opacity 属性 (32)
- transition 属性 (33)