我正在使用ExtJS+mongoDB实现一个应用程序。我使用node.js作为服务器,并使用express模块创建REST api。具体来说,我使用的是:MongoDB4.1.3+Mongoos1.2.17+ ExtJS 1.2.17 +MongoDB2.4,运行在Node.js v0.10.3上。
代码ExtJS部件(在MVC中组织):
模型部分包含两个模型,PvdcPrice和PvdcPriceDetails,它们具有"hasMany“关系。
PvdcPrice.js:
Ext.define('App.model.PvdcPrice', {
extend : 'Ext.data.Model',
fields : [{
name : '_id',
type : 'Number'
}, {
name : 'Type',
type : 'string'
}, {
name : 'MaxDiscount',
type : 'Number'
}],
hasMany : [{
name : 'prices',
model : 'App.model.PvdcPriceDetail',
associationKey : 'prices'
}],
proxy : {
type : 'rest',
url : '/pvdcprices',
reader : {
type : 'json',
root : 'data',
successProperty : 'success'
}
}
});PvdcPriceDetail.js:
Ext.define('App.model.PvdcPriceDetail', {
extend : 'Ext.data.Model',
fields : [{
name : 'ID',
type : 'Number'
}, {
name : 'Location',
type : 'string'
}, {
name : 'Edition',
type : 'string'
}, {
name : 'MonthlyPrice',
type : 'Number'
}, {
name : 'OneTimePrice',
type : 'Number'
}
]
});控制器部分,因为它太长了,我在这里只放了商店创建部分:
var pvdcPrice = Ext.create('Ext.data.Store', {
model : "App.model.PvdcPrice",
data : [{
"_id" : 1,
"Type" : "pvdc",
"MaxDiscount" : "0"
}]
});
var priceInfo = pvdcPrice.first();
var pvdcPriceDetails = priceInfo.prices();
pvdcPriceDetails.add({
'ID' : 1,
'Location' : 'SNJ',
'Edition' : 'Basic',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
});
pvdcPriceDetails.add({
'ID' : 2,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
});
pvdcPriceDetails.add({
'ID' : 3,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
});
pvdcPrice.sync();
var record = pvdcPrice.first();
console.log(record.get('Type'));
record.prices().each(function(r) {
console.log(r.get('Location'));
console.log(r.get('Edition'));
});对于Node.js部件,服务器脚本为app.js:
var express = require('express'),
app = module.exports = express();
// MongoDB
var mongoose = require('mongoose'),
db = mongoose.connect('mongodb://127.0.0.1/IaaSDB'),
//create sub schema of pvdc price schema
PriceDetailSchema = new mongoose.Schema({
ID: Number,
Location: String,
Edition: String,
MonthlyPrice: Number,
OneTimePrice: Number
}),
//create the Pvdc price info Model using the 'pvdcPrice' collection as a data-source
PvdcPrice = mongoose.model('pvdcPrice', new mongoose.Schema({
Type: String,
MaxDiscount: String,
prices: [PriceDetailSchema]
}));
// Configuration
app.configure(function () {
//app.set('views', __dirname + '/views');
//app.set('view engine', 'jade');
app.use(express.bodyParser());//parse JSON into objects
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/IaaSPriceTool'));
});
app.configure('development', function () {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});
app.configure('production', function () {
app.use(express.errorHandler());
});
// Routes
app.get('/', function (req, res) {
res.redirect('/index.html');
});
/*
Pvdc Price Information CRUD web service
*/
app.get('/pvdcprices', function (req, res) {
PvdcPrice.find({}, function (err, pvdcprices) {
res.contentType('json');
res.json({
success: true,
data: pvdcprices
});
});
});
app.get('/pvdcprices/:id', function(req, res){
PvdcPrice.find({_id: req.params.id}, function (err, pvdcPrices) {
res.contentType('json');
res.json({
success: true,
data: pvdcPrices
});
});
});
app.post('/pvdcprices', function (req, res) {
console.log("[200] " + req.method + " to " + req.url);
console.log(req.body);
var newPriceInfo = new PvdcPrice();
var newPriceInfoData = req.body;
//remove the id which the client sends since it is a new pvdc price
delete newPriceInfo['_id'];
newPriceInfo.set(newPriceInfoData);
newPriceInfo.save(function (err, pvdcPrice) {
res.contentType('json');
res.json({
success: !err,
data: pvdcPrice
});
});
});
app.listen(3000);
console.log("Express server listening on port %d in %s mode", 3000, app.settings.env);然后,我使用firebug调试前端,我可以从浏览器控制台看到pvdc价格的竞争:
POST http://localhost:3000/pvdcprices?_dc=1369740182183 200 OK 27ms
pvdc
Basic
ATL
Standard
ATL
Standard这意味着ExtJS中的关联模型可以工作,我可以看到pvdcPrice的内容。ExtJS中的json结构应该是:
{
"data" :{
"_id" : 1,
"Type" : "pvdc",
"MaxDiscount" : "0",
"prices" : [{
'ID' : 1,
'Location' : 'SNJ',
'Edition' : 'Basic',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
},{
'ID' : 2,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
},{
'ID' : 3,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
}]
}
}但node.js的回应是成功:假。
然后在node.js部件的控制台中,我用node.js打印post的请求体,它是:
[200] POST to /pvdcprices?_dc=1369734975208
{ _id: 1, Type: 'pvdc', MaxDiscount: 0, id: null }缺少“价格”的子内容,只将pvdcPrice的主要部分发布到服务器。
谁能指出开机自检过程中丢失的原因?非常感谢您的帮助:)
发布于 2013-05-29 21:54:37
最终解决了这个问题,关键是ExtJS 4中的Ext.data.writer.Json没有很好的支持关联。
http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single-Store
这个链接提供了一些解决方案。
我使用Extjs4.1.1a,并将DeepJson添加到Extjs4.1源文件夹中:
/**
* @class Ext.data.writer.DeepJson This class is used to write
* {@link Ext.data.Model} data to the server in a JSON format.
*
* It overrides the original Ext.data.writer.Json since the Json can not handle
* hasMany association, it can only transform the outside part into Json, the
* inside data will be omiited.
*
* @Yi Fang Reference:
* http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single-Store/page3 23 Mar 2012 6:00 AM
* http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single-Store/page5 13 Feb 2013 2:57 PM
*
*/
Ext.define('Ext.data.writer.DeepJson', {
extend : 'Ext.data.writer.Json',
getRecordData : function(record, operation) {
// Setup variables
var me = this, i, association, childStore, data;
data = me.callParent(arguments);
// Iterate over all the hasMany associations
for (i = 0; i < record.associations.length; i++) {
association = record.associations.get(i);
if (association.type == 'hasMany') {
data[association.name] = null;
childStore = record[association.storeName];
// Iterate over all the children in the current
// association
childStore.each(function(childRecord) {
if (!data[association.name]) {
data[association.name] = [];
}
// Recursively get the record data for
// children (depth first)
var childData = this.getRecordData.call(
this, childRecord);
/*
* If the child was marked dirty or phantom
* it must be added. If there was data
* returned that was neither dirty or
* phantom, this means that the depth first
* recursion has detected that it has a
* child which is either dirty or phantom.
* For this child to be put into the
* prepared data, it's parents must be in
* place whether they were modified or not.
*/
if (childRecord.dirty
|| childRecord.phantom
|| (childData != null)) {
data[association.name].push(childData);
record.setDirty();
}
}, me);
/*
* Iterate over all the removed records and add them to
* the preparedData. Set a flag on them to show that
* they are to be deleted
*/
Ext.each(childStore.removed, function(
removedChildRecord) {
// Set a flag here to identify removed
// records
removedChildRecord.set('forDeletion', true);
var removedChildData = this.getRecordData
.call(this, removedChildRecord);
data[association.name]
.push(removedChildData);
record.setDirty();
}, me);
}
}
// Only return data if it was dirty, new or marked for deletion.
if (record.dirty || record.phantom || record.get('forDeletion')) {
return data;
}
return null;
}
});在PvdcPrice模型中,将代理更新为
proxy : {
type : 'rest',
url : '/pvdcprices',
reader : {
type : 'json',
root : 'data',
successProperty : 'success'
},
writer : Ext.create('Ext.data.writer.DeepJson')
}然后嵌套数据的post就可以工作了。
发布于 2013-05-28 18:32:54
'App.model.PvdcPriceDetail'模型类中缺少belongsTo: 'App.model.PvdcPrice'。这是代码中的一个关联问题,您需要将父类键映射到子模型。请参考下面的链接(在关联会话中)。
http://docs.sencha.com/extjs/4.2.0/#!/guide/data
我希望在将您的belongsTo配置设置为'App.model.PvdcPriceDetail‘类之后,它会像预期的那样正常工作。
谢谢
https://stackoverflow.com/questions/16789597
复制相似问题