You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Handlebars页面无法显示MySQL获取的数据

Express + Sequelize + Handlebars 页面无法显示数据的问题排查与修复

我正在使用Express、Sequelize和MySQL数据库,尝试在Handlebars页面展示航班列表。控制台中能正常输出查询到的数据,但Handlebars页面却无任何内容显示。刚学习Node.js中的Handlebars和Express用法,不知道哪里出了问题。


原app.js代码

//importações de módulos
const express = require("express");
const app = express();
const handlebars = require("express-handlebars");
const path = require("path");
const Sequelize = require("sequelize");

//conectando com o banco
const sequelize = new Sequelize("db", "user", "password", {
    host: "host",
    dialect: "mysql"
})

sequelize.authenticate().then(function(){
    console.log("deu certo!");
}).catch(function(){
    console.log("aAaAaAaAaAaAai")
})

const Voo = sequelize.define("Voo", {
    ID_VOO: {
        type: Sequelize.INTEGER(100), 
        primaryKey: true,
        autoIncrement: true,
    },
    ORIGEM: {
        type: Sequelize.STRING,
        allowNull: false,
    },
    DESTINO: {
        type: Sequelize.STRING,
        allowNull: false,
    },
    DT_PARTIDA: {
        type: Sequelize.DATE,
        allowNull: false,
    },
    DT_CHEGADA: {
        type: Sequelize.DATE,
        allowNull: false,
    },
    HR_SAIDA: {
        type: Sequelize.TIME,
        allowNull: false,
    },
    HR_CHEGADA: {
        type: Sequelize.TIME,
        allowNull: false,
    },
    VO_AERONAVE: {
        type: Sequelize.INTEGER,
        allowNull: false,
    }

}, {tableName: "voo", 
    timestamps: false,
})

//sincronizando model com banco de dados
Voo.sync().then(() => {
    console.log('Tabela sincronizada com sucesso');
  })
  .catch((error) => {
    console.error('Erro ao sincronizar tabela:', error);
  });

//buscando registros no banco
Voo.findAll().then((voos) => {
    app.post("/passagensAereas", function(req, res){
        res.render("passagensAereas", {voos: voos});
        //res.send("testando" + req.body.Origem + "\n" + req.body.Destino + "\n" + req.body.dataSaida);
    })
}).catch((error) => {
    console.error('Erro ao consultar tabela:', error);
  });
  
//=========================================================================================


//config
    //template engine
    app.engine('handlebars', handlebars.engine({defaultLayout: 'main'}));
    app.set('view engine', 'handlebars');

app.use(express.urlencoded({extended: false}));
app.use(express.json());
app.use(express.static('public'));

//rotas
app.get("/", function(req, res){
    res.render("index");
})


app.listen(8083, function(){
    console.log("aAaAaAaAai está funcionando mesmo")
})

原Handlebars页面代码

<body>
    <header>
        <img src="img/Logo-SKYIFSP.png">
    </header>
    <section>
        <div id="passagensAereas">
            <h2>Passagens aéreas</h2>
            <div id="box">
                <h1>Lista de voos</h1>
                <ul> 
                    {{#each voos}}
                    <li>{{this.origem}}</li>
                    {{/each}}
                </ul>
            </div>
        </div>
    </section>
    <footer>
        <h5 id="copyright">© 2022 - 2023 Symcode soluções de software - Todos os direitos reservados.</h5>
    </footer>
</body>

问题排查与修复方案

你的代码存在三个核心问题,导致页面无法显示数据:

1. 路由请求类型错误

你给/passagensAereas注册的是POST路由,但访问页面时浏览器发送的是GET请求,所以这个路由永远不会被触发。需要把app.post改成app.get。

2. 路由定义时机错误

你将路由定义放在了Voo.findAll()的回调中,这会导致只有当数据库查询完成后路由才会被注册。更合理的做法是在路由内部执行数据库查询,这样每次请求该页面时都会获取最新数据,也避免了路由注册延迟的问题。

3. Handlebars字段名大小写不匹配

你的Sequelize模型中定义的字段是大写的ORIGEM,但Handlebars模板中使用的是小写的origem。默认情况下Sequelize会返回和数据库字段名一致的属性,所以模板里应该使用大写的this.ORIGEM。


修改后的代码

修改后的app.js

//importações de módulos
const express = require("express");
const app = express();
const handlebars = require("express-handlebars");
const path = require("path");
const Sequelize = require("sequelize");

//conectando com o banco
const sequelize = new Sequelize("db", "user", "password", {
    host: "host",
    dialect: "mysql"
})

sequelize.authenticate().then(function(){
    console.log("deu certo!");
}).catch(function(){
    console.log("aAaAaAaAaAaAai")
})

const Voo = sequelize.define("Voo", {
    ID_VOO: {
        type: Sequelize.INTEGER(100), 
        primaryKey: true,
        autoIncrement: true,
    },
    ORIGEM: {
        type: Sequelize.STRING,
        allowNull: false,
    },
    DESTINO: {
        type: Sequelize.STRING,
        allowNull: false,
    },
    DT_PARTIDA: {
        type: Sequelize.DATE,
        allowNull: false,
    },
    DT_CHEGADA: {
        type: Sequelize.DATE,
        allowNull: false,
    },
    HR_SAIDA: {
        type: Sequelize.TIME,
        allowNull: false,
    },
    HR_CHEGADA: {
        type: Sequelize.TIME,
        allowNull: false,
    },
    VO_AERONAVE: {
        type: Sequelize.INTEGER,
        allowNull: false,
    }

}, {tableName: "voo", 
    timestamps: false,
    // 可选:开启后自动将数据库大写/下划线字段转为驼峰命名
    // underscored: true
})

//sincronizando model com banco de dados
Voo.sync().then(() => {
    console.log('Tabela sincronizada com sucesso');
  })
  .catch((error) => {
    console.error('Erro ao sincronizar tabela:', error);
  });

//config
//template engine
app.engine('handlebars', handlebars.engine({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');

app.use(express.urlencoded({extended: false}));
app.use(express.json());
app.use(express.static('public'));

//rotas
app.get("/", function(req, res){
    res.render("index");
})

// 修改为GET路由,并在路由内部查询数据库
app.get("/passagensAereas", async function(req, res){
    try {
        const voos = await Voo.findAll();
        console.log(voos); // 保留打印确认数据
        res.render("passagensAereas", {voos: voos});
    } catch (error) {
        console.error('Erro ao consultar tabela:', error);
        res.status(500).send('Erro ao carregar voos');
    }
})

app.listen(8083, function(){
    console.log("aAaAaAaAai está funcionando mesmo")
})

修改后的Handlebars模板

<body>
    <header>
        <img src="img/Logo-SKYIFSP.png">
    </header>
    <section>
        <div id="passagensAereas">
            <h2>Passagens aéreas</h2>
            <div id="box">
                <h1>Lista de voos</h1>
                <ul> 
                    {{#each voos}}
                    <li>{{this.ORIGEM}}</li>
                    {{/each}}
                </ul>
                <!-- 添加空数据提示,便于调试 -->
                {{#if (empty voos)}}
                <p>Nenhum voo encontrado</p>
                {{/if}}
            </div>
        </div>
    </section>
    <footer>
        <h5 id="copyright">© 2022 - 2023 Symcode soluções de software - Todos os direitos reservados.</h5>
    </footer>
</body>

可选优化:字段名驼峰化

如果你希望Handlebars里用小写的origem,可以在Sequelize模型中为字段添加field配置,映射数据库的大写字段:

const Voo = sequelize.define("Voo", {
    idVoo: {
        type: Sequelize.INTEGER(100), 
        primaryKey: true,
        autoIncrement: true,
        field: 'ID_VOO'
    },
    origem: {
        type: Sequelize.STRING,
        allowNull: false,
        field: 'ORIGEM'
    },
    // 其他字段同理配置...
}, {tableName: "voo", 
    timestamps: false,
})

这样模板里就可以用this.origem来访问数据了。

内容的提问来源于stack exchange,提问作者Sarah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 13:09:55