所以,我想要做的是向模型实例添加一个属性。正如这里提到的 Add Property to Object that is returned by Sequelize FindOne
和 sequelize 文档。使用 setDataValue()
添加属性将起作用。
考虑这个例子。
instance = await model.findOne({where: ...})
newColumnValue = instance.definedColumn * 15;
instance.setDataValue("newColumn", newColumnValue);
//calling data through json
//this works fine
res.json({data: instance});
我可以使用上面的代码查看我的新列及其值。但是,我想呈现我的 Handlebars 模板。所以,我做...
res.render("hbsFile", {data: instance});
在我的 .hbs 文件中,它似乎无法使用
newColumn
读取 {{data.newColumn}}
但是,如果我这样做
解决方法 1
//transform my instance to JSON
instance.setDataValue("newColumn", newColumnValue);
instance = instance.get({plain: true});
res.render("hbsFile", {data: instance});
解决方法 2
//instead of using setDataValue
//associate property like in POJO
instance.newColumn = newColumnValue;
res.render("hbsFile", {data: instance});
使用这两种解决方案,我都可以访问 .hbs 文件中的
{{data.newColumn}}
。问题
问题 1:哪种 解决方法 (如果有)是正确的方法?什么是替代方案?
问题 #2:为什么不像
res.render()
那样表达 toJSON()
调用 sequelize 的 res.json()
方法?
最佳答案
Express 的 res.json
调用 JSON.stringify()
,如 docs 所述,后者又调用实例(Sequelize 的) toJSON
。
另一方面 res.render
调用 app.render
,后者调用 view.render
,最终调用模板引擎。在整个过程中,各种选项被合并,但据我在代码和文档中注意到,您提供的数据没有调用 toJSON
。该对象只是在整个过程中传递给模板引擎,如果模板引擎试图通过 instance['newColumn']
访问该属性,它可能会读取 undefined 因为 setDataValue
实现: instance.dataValues[key] = value
。
Sequelize 的实例将它们的值存储在 dataValues
对象中,并在您通过点符号访问它们时使用 getter 来获取这些值。这可能导致某些情况下 getter 未正确映射或由于某种原因无法检索属性表单 dataValues
。我个人在将对象传播到一个新对象并将该新对象传递到其他地方时遇到了这个问题。
您始终可以使用的一种解决方法是执行 {data: instance.dataValues}
或使用您发现的普通选项(在大多数情况下基本上做同样的事情,但更清晰,因为 dataValues
并不是真的打算直接访问)。
第二种解决方法当然是自己调用 toJSON
函数,然后将结果解析回普通对象。
这两种方法不仅完全有效,而且设计也很好,因为您不应将“跟踪”的 ORM 模型作为 View 模型传递(您在第二个解决方法中正在这样做)。这样做会将您的数据库暴露给不应访问它的应用程序层,并可能导致意外行为。
TLDR: 解决方法 1 是更好的方法
关于node.js - res.render 不加载 Sequelize 数据值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55203532/