
本文详解如何在 Next.js API 路由中正确导入并使用 Sequelize 模型,解决因模块加载、实例初始化或连接未建立导致的 Recette is undefined 等常见问题。
本文详解如何在 next.js api 路由中正确导入并使用 sequelize 模型,解决因模块加载、实例初始化或连接未建立导致的 `recette is undefined` 等常见问题。
在 Next.js(作为后端 API 服务)中集成 Sequelize 时,常见的错误并非逻辑缺陷,而是模块导出/导入方式不匹配与Sequelize 实例未统一注入所致。你遇到的 console.log(Recette) 输出 undefined 或 [Function (anonymous)],本质是模型未被正确初始化或未绑定数据库连接实例。
✅ 正确结构:分离连接、模型定义与使用
1. 统一数据库连接管理(lib/database.js)
import { Sequelize } from 'sequelize';
const sequelize = new Sequelize(
process.env.DB_NAME || 'recettes_db',
process.env.DB_USER || 'postgres',
process.env.DB_PASSWORD || '',
{
host: process.env.DB_HOST || 'localhost',
dialect: 'postgres',
logging: process.env.NODE_ENV === 'development' ? console.log : false,
pool: { max: 5, min: 0, acquire: 30000, idle: 10000 },
}
);
// 验证连接(仅用于启动时诊断)
(async () => {
try {
await sequelize.authenticate();
console.log('✅ PostgreSQL connection established successfully.');
} catch (err) {
console.error('❌ Unable to connect to the database:', err.message);
}
})();
export default sequelize;
⚠️ 注意:
.authenticate()是异步操作,但无需await在导出前——它仅作连接测试;真正关键的是sequelize实例本身被导出供模型复用。
2. 正确定义模型(models/recette.js)
import { DataTypes, Model } from 'sequelize';
import sequelize from '../lib/database'; // ✅ 关键:复用同一 sequelize 实例
class Recette extends Model {
static associate(models) {
Recette.belongsTo(models.Difficulte, {
foreignKey: 'id_difficulte',
as: 'difficulte',
});
Recette.belongsTo(models.Categorie, {
foreignKey: 'id_categorie',
as: 'categorie',
});
}
static async getAllRecette() {
console.log('? Fetching all recipes...');
return this.findAll({
include: ['difficulte', 'categorie'], // 自动关联预加载
order: [['nom', 'ASC']],
});
}
}
// ✅ 使用类静态方法 init,并传入外部 sequelize 实例
Recette.init(
{
nom: { type: DataTypes.STRING, allowNull: false },
description: DataTypes.TEXT,
portion: DataTypes.INTEGER,
temps: DataTypes.INTEGER,
id_difficulte: DataTypes.INTEGER,
id_categorie: DataTypes.INTEGER,
image: DataTypes.TEXT,
},
{
sequelize,
modelName: 'Recette',
tableName: 'recettes', // 显式指定表名(可选,避免复数自动转换)
timestamps: true,
}
);
export default Recette;
✅ 关键点:
- 不再导出
(sequelize, DataTypes) => {...}工厂函数(这是旧版 Sequelize v5/v6 的 CommonJS 模式);- 改用 ES 模块直接
export default Recette,并在init()中显式传入sequelize;- 所有模型均从
../lib/database导入同一实例,确保连接一致性。
3. 在 API 路由控制器中安全使用(pages/api/recettes/index.js)
import Recette from '../../models/recette'; // ✅ 正确:默认导出,无解构
export default async function handler(req, res) {
if (req.method !== 'GET') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const recettes = await Recette.getAllRecette(); // ✅ 可调用静态方法
// 或直接:const recettes = await Recette.findAll();
res.status(200).json({
success: true,
count: recettes.length,
data: recettes,
});
} catch (error) {
console.error('? Recette fetch error:', error);
res.status(500).json({
success: false,
error: 'Failed to retrieve recipes',
details: process.env.NODE_ENV === 'development' ? error.message : undefined,
});
}
}
❌ 常见错误排查清单
- [ ] 混用
require()和import:Next.js App Router(或 Pages Router 启用 ES 模块)必须统一使用import;禁用require()。 - [ ] 模型未
init()或未传入sequelize实例:导致Recette是空类,无数据库行为。 - [ ] 环境变量缺失:检查
.env.local是否配置了DB_NAME,DB_USER,DB_PASSWORD,DB_HOST。 - [ ] PostgreSQL 服务未运行或端口被占用:本地测试可用
docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=pass postgres快速启动。 - [ ] 模型文件未被 Next.js 解析:确保路径正确(如
../../models/recette),且文件扩展名为.js(非.ts除非已配 TypeScript)。
✅ 进阶建议
- 将所有模型集中注册(如
models/index.js),便于一键同步(sync()); - 在
getServerSideProps或generateStaticParams中调用模型需注意:仅限服务端执行,不可在客户端组件中直接 import 模型; - 对敏感操作(如创建/更新)添加事务(
sequelize.transaction())和参数校验(如zod)。
通过以上结构化组织,你将彻底告别 undefined model 问题,构建出稳定、可维护的 Next.js + Sequelize 后端服务层。











