因此,我想做的是向模型实例添加属性。如此处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()
方法呢?
答案 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是更好的方法