res.render不会加载sequelize数据值

时间:2019-03-17 03:16:57

标签: node.js express sequelize.js

因此,我想做的是向模型实例添加属性。如此处Add Property to Object that is returned by Sequelize FindOne 和续集文档所述。使用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});

上面的代码可以看到我的新列及其值。但是,我想渲染我的车把模板。所以,我愿意...

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()调用序列的res.json()方法呢?

1 个答案:

答案 0 :(得分:2)

Express的res.json调用docs中所述的JSON.stringify(),而后者依次调用实例的(Sequelize的)toJSON

另一方面,res.render调用app.render,后者调用view.render,最后调用模板引擎。在整个过程中,各种选项被合并,但是据我设法在代码和文档中都注意到的那样,在您提供的数据上没有调用toJSON。该对象只是在整个过程中传递给模板引擎,并且如果模板引擎尝试通过instance['newColumn']访问属性,则由于setDataValue实现会执行以下操作,因此它可能会读取未定义的内容:instance.dataValues[key] = value

Sequelize的实例将其值存储在dataValues对象中,并在通过点表示法访问它们时使用getter获取值。这可能导致某些情况,由于某种原因,吸气剂未正确映射或无法检索属性表单dataValues。当我将对象散布到一个新对象并将该新对象传递到其他地方时,我个人遇到了这个问题。

您可以始终使用的一种解决方法是执行{data: instance.dataValues}或使用发现的普通选项(在大多数情况下,这基本上是相同的事情,但是由于dataValues并不是很干净旨在直接访问。)

第二种解决方法当然是自己调用toJSON函数,然后将结果解析回一个普通对象。

这两种方法不仅非常有效,而且设计良好,因为您不应将“跟踪的” ORM模型作为视图模型传递(这是您在第二种解决方法中所做的)。这样做会使您的数据库暴露于不应访问该应用程序的应用程序层,并可能导致意外行为。


TLDR:解决方法1是更好的方法