<think>我们将使用Flask作为后端框架,Layui作为前端UI框架,PostgreSQL作为数据库。
功能需求:
1. 表格展示数据(支持分页)
2. 搜索条件表单,提交到后端进行过滤
3. 实现增删改查(CRUD)操作
步骤:
1. 设计数据库表(假设我们有一个名为`item`的表,包含id, name, description, create_time等字段)
2. 使用Flask连接PostgreSQL
3. 编写后端API:
- 获取数据(带分页和搜索条件)
- 添加数据
- 修改数据
- 删除数据
4. 前端使用Layui的表格模块、表单模块、弹层模块等
由于代码量较大,我们将分步骤实现。
第一步:创建数据库表(PostgreSQL)
假设我们创建的表名为`items`,包含以下字段:
id: 主键,自增
name: 字符串
description: 文本
create_time: 时间戳,默认当前时间
SQL语句:
```sql
CREATE TABLE items (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
第二步:Flask项目结构
项目结构如下:
app.py # 主程序
config.py # 配置文件
templates/ # 模板文件夹
index.html # 主页面
第三步:编写Flask应用
我们先安装必要的包(使用pip):
pip install flask flask-sqlalchemy psycopg2-binary
注意:flask-sqlalchemy用于操作数据库,psycopg2是PostgreSQL的适配器。
开始编写代码:
1. 配置文件 config.py
```python
# config.py
import os
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'
SQLALCHEMY_DATABASE_URI = 'postgresql://username:password@localhost/dbname'
SQLALCHEMY_TRACK_MODIFICATIONS = False
```
2. app.py
我们将在这个文件中创建Flask应用,并设置路由。
由于代码较长,我们分块编写。
首先,初始化Flask和SQLAlchemy:</think>下面是一个使用 Flask + Layui + PostgreSQL 实现表格 CRUD 功能的完整解决方案,包含搜索、分页和表单操作:
### 解决方案步骤
1. **环境准备**
2. **数据库设计**
3. **后端 API 实现**
4. **前端页面实现**
5. **整合与运行**
---
### 1. 环境准备
安装所需依赖:
```bash
pip install flask flask-sqlalchemy psycopg2-binary
```
---
### 2. 数据库设计 (PostgreSQL)
创建 `products` 表:
```sql
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
category VARCHAR(50),
price DECIMAL(10,2),
stock INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
---
### 3. 后端实现 (Flask + SQLAlchemy)
#### `app.py` 文件:
```python
from flask import Flask, request, jsonify, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://user:password@localhost/dbname'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# 数据模型
class Product(db.Model):
__tablename__ = 'products'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
category = db.Column(db.String(50))
price = db.Column(db.Numeric(10,2))
stock = db.Column(db.Integer)
created_at = db.Column(db.DateTime, server_default=db.func.now())
# CRUD 接口
@app.route('/')
def index():
return render_template('index.html')
# 获取数据(带搜索)
@app.route('/api/products', methods=['GET'])
def get_products():
# 获取搜索参数
name = request.args.get('name', '')
category = request.args.get('category', '')
min_price = request.args.get('min_price', 0, type=float)
# 构建查询
query = Product.query
if name:
query = query.filter(Product.name.ilike(f'%{name}%'))
if category:
query = query.filter_by(category=category)
if min_price > 0:
query = query.filter(Product.price >= min_price)
# 分页处理
page = request.args.get('page', 1, type=int)
per_page = request.args.get('limit', 10, type=int)
pagination = query.paginate(page=page, per_page=per_page)
# 返回JSON数据
return jsonify({
'code': 0,
'msg': '',
'count': pagination.total,
'data': [{
'id': p.id,
'name': p.name,
'category': p.category,
'price': float(p.price),
'stock': p.stock,
'created_at': p.created_at.isoformat()
} for p in pagination.items]
})
# 添加数据
@app.route('/api/products', methods=['POST'])
def add_product():
data = request.get_json()
new_product = Product(
name=data['name'],
category=data['category'],
price=data['price'],
stock=data['stock']
)
db.session.add(new_product)
db.session.commit()
return jsonify({'code': 0, 'msg': '添加成功'})
# 更新数据
@app.route('/api/products/<int:id>', methods=['PUT'])
def update_product(id):
product = Product.query.get_or_404(id)
data = request.get_json()
product.name = data['name']
product.category = data['category']
product.price = data['price']
product.stock = data['stock']
db.session.commit()
return jsonify({'code': 0, 'msg': '更新成功'})
# 删除数据
@app.route('/api/products/<int:id>', methods=['DELETE'])
def delete_product(id):
product = Product.query.get_or_404(id)
db.session.delete(product)
db.session.commit()
return jsonify({'code': 0, 'msg': '删除成功'})
if __name__ == '__main__':
app.run(debug=True)
```
---
### 4. 前端实现 (Layui)
#### `templates/index.html` 文件:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>产品管理系统</title>
<link href="https://cdn.jsdelivr.net/npm/layui@2.6.8/dist/css/layui.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/layui@2.6.8/dist/layui.js"></script>
</head>
<body>
<div class="layui-container">
<!-- 搜索表单 -->
<form class="layui-form layui-card-header" style="margin-top:20px">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">产品名称</label>
<div class="layui-input-inline">
<input type="text" name="name" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">类别</label>
<div class="layui-input-inline">
<select name="category">
<option value="">全部</option>
<option value="电子产品">电子产品</option>
<option value="食品">食品</option>
<option value="服装">服装</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">最低价格</label>
<div class="layui-input-inline">
<input type="number" name="min_price" class="layui-input">
</div>
</div>
<div class="layui-inline">
<button class="layui-btn" lay-submit lay-filter="search">搜索</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
<button class="layui-btn layui-btn-normal" type="button" id="addBtn">添加产品</button>
</div>
</div>
</form>
<!-- 数据表格 -->
<table id="productTable" lay-filter="productTable"></table>
</div>
<!-- 添加/编辑表单弹窗 -->
<script type="text/html" id="formDialog">
<form class="layui-form" style="padding:20px">
<input type="hidden" name="id">
<div class="layui-form-item">
<label class="layui-form-label">产品名称</label>
<div class="layui-input-block">
<input type="text" name="name" required lay-verify="required" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">类别</label>
<div class="layui-input-block">
<select name="category" lay-verify="required">
<option value="">请选择</option>
<option value="电子产品">电子产品</option>
<option value="食品">食品</option>
<option value="服装">服装</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">价格</label>
<div class="layui-input-block">
<input type="number" name="price" required lay-verify="required|number" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">库存</label>
<div class="layui-input-block">
<input type="number" name="stock" required lay-verify="required|number" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="formSubmit">提交</button>
</div>
</div>
</form>
</script>
<!-- 操作列模板 -->
<script type="text/html" id="operateTpl">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
</script>
<script>
layui.use(['table', 'form', 'layer'], function(){
var table = layui.table;
var form = layui.form;
var layer = layui.layer;
var $ = layui.$;
// 初始化表格
var tableIns = table.render({
elem: '#productTable',
url: '/api/products',
page: true,
cols: [[
{field: 'id', title: 'ID', width: 80},
{field: 'name', title: '产品名称'},
{field: 'category', title: '类别', width: 120},
{field: 'price', title: '价格', width: 120, sort: true},
{field: 'stock', title: '库存', width: 100},
{field: 'created_at', title: '创建时间', width: 180},
{title: '操作', toolbar: '#operateTpl', width: 150}
]]
});
// 搜索表单提交
form.on('submit(search)', function(data){
tableIns.reload({
where: data.field,
page: {curr: 1}
});
return false;
});
// 添加按钮事件
$('#addBtn').click(function(){
layer.open({
type: 1,
title: '添加产品',
area: '500px',
content: $('#formDialog').html()
});
form.render();
});
// 表格操作事件
table.on('tool(productTable)', function(obj){
var data = obj.data;
if(obj.event === 'del'){
layer.confirm('确定删除吗?', function(index){
$.ajax({
url: '/api/products/' + data.id,
type: 'DELETE',
success: function(){
layer.close(index);
tableIns.reload();
}
});
});
} else if(obj.event === 'edit'){
layer.open({
type: 1,
title: '编辑产品',
area: '500px',
content: $('#formDialog').html(),
success: function(){
form.val('form', {
id: data.id,
name: data.name,
category: data.category,
price: data.price,
stock: data.stock
});
}
});
form.render();
}
});
// 表单提交事件
form.on('submit(formSubmit)', function(data){
var method = data.field.id ? 'PUT' : 'POST';
var url = data.field.id ? '/api/products/' + data.field.id : '/api/products';
$.ajax({
url: url,
type: method,
contentType: 'application/json',
data: JSON.stringify(data.field),
success: function(){
layer.closeAll();
tableIns.reload();
}
});
return false;
});
});
</script>
</body>
</html>
```
---
### 5. 功能说明
1. **搜索功能**:
- 支持按名称模糊查询
- 按类别筛选
- 按价格范围过滤
2. **CRUD 操作**:
- 添加:点击"添加产品"按钮
- 编辑:点击表格行的编辑按钮
- 删除:点击表格行的删除按钮
- 查看:表格自动加载数据
3. **分页功能**:
- Layui 表格内置分页
- 后端实现分页查询
4. **表单验证**:
- 必填字段验证
- 数字类型验证
---
### 运行步骤
1. 创建 PostgreSQL 数据库和表
2. 启动 Flask 应用:
```bash
python app.py
```
3. 访问 `http://localhost:5000`
---
### 技术栈说明
| 技术 | 作用 |
|--------------|-------------------------------|
| **Flask** | Python 后端框架 |
| **SQLAlchemy** | ORM 数据库操作库 |
| **Layui** | 前端 UI 框架 |
| **PostgreSQL**| 关系型数据库 |
| **jQuery** | AJAX 请求处理 |