我正在访问一个REST服务,它公开这两个资源,一个父资源和一个子资源:
/users
/users/{userId}/account
因此资源“account”不嵌套在资源“user”中,它必须由第二个请求访问。这些REST API有一些例子,例如here
我使用这些模型将用户及其帐户映射到Ext Js 4数据模型:
用户
Ext.define("MyApp.model.User", {
extend: "Ext.data.Model",
fields: [ { name: "id", type: "string" }],
associations: [{
model: "MyApp.model.Account",
name: "account",
type: "hasOne",
reader: "json",
getterName: "getAccount",
setterName: "setAccount",
foreignKey: "accountId"
}
],
proxy: {
type: "rest",
url: "/rest/users",
reader: {
type: "json",
totalProperty: "total",
root: "users"
}
}
});
帐户
Ext.define("MyApp.model.Account", {
extend: "Ext.data.Model",
fields: [ { name: "id", type: "string" }],
belongsTo: "MyApp.model.User",
proxy: {
type: "rest",
reader: { type: "json"}
}
});
帐户代理没有网址(我希望这会根据父用户模型创建)。当我调用user.getAccount()时,我得到一个异常,因为代理缺少url。
问题:是否有某种方法来设置模型,以便Ext Js将访问/ users / {userId} / account而无需使用每个父userId手动更新帐户代理URL?< / em>的
答案 0 :(得分:26)
你不会从库存Ext类中获得你想要的东西,你将不得不变得有点脏......
根据我的理解,您需要用户的ID来加载其帐户,而不是帐户记录本身的ID。所以,我会配置关联来反映:
associations: [{
model: "MyApp.model.Account",
name: "account",
type: "hasOne",
reader: "json",
getterName: "getAccount",
setterName: "setAccount",
// foreignKey: "accountId"
foreignKey: 'id'
}],
这里的一大优势是,当系统要求用户ID为请求构建网址时,用户ID可用。
现在,为了使用您需要的格式构建网址,我们必须替换代理的buildUrl
方法。而且,正如您已经发现的那样,您首先需要一个URL才能使用此方法。
所以,这是我如何配置帐户代理:
proxy: {
type: "rest",
reader: {type: "json"},
// Give it an URL to avoid the error
url: '/rest/users/{}/account',
// Replace the buildUrl method
buildUrl: function(request) {
var me = this,
operation = request.operation,
records = operation.records || [],
record = records[0],
url = me.getUrl(request),
id = record ? record.getId() : operation.id;
// Here's the part honoring your URL format
if (me.isValidId(id)) {
url = url.replace('{}', id);
} else {
throw new Error('A valid id is required');
}
// That's enough, but we lose the cache buster param (see bellow)
return url;
// If we want the cache buster param (_dc=...) to be added,
// we must call the superclass, which will read the url from
// the request.
request.url = url;
return Ext.data.proxy.Rest.superclass.buildUrl.apply(this, arguments);
}
}
此时,我们最终会在表单的网址上发出代理触发请求:
rest/users/45/account?id=45
这只是化妆品,但是id查询参数让我烦恼,所以我也会用下面的方法替换代理的buildRequest
方法:
buildRequest: function(operation, callback, scope) {
var me = this,
params = operation.params = Ext.apply({}, operation.params, me.extraParams),
request;
Ext.applyIf(params, me.getParams(operation));
// if (operation.id !== undefined && params[me.idParam] === undefined) {
// params[me.idParam] = operation.id;
// }
request = new Ext.data.Request({
params : params,
action : operation.action,
records : operation.records,
operation: operation,
url : operation.url,
proxy: me
});
request.url = me.buildUrl(request);
operation.request = request;
return request;
}
并且,在这里......虽然它可行,但我并不真的建议在代理的配置中以这种方式覆盖方法。在现实生活中,你应该从Rest中扩展你自己的代理类,特别是如果你需要配置许多这样的代理......但我希望我给你开始所需的所有成分!
答案 1 :(得分:5)
我遇到了同样的问题,我发现rixo的答案绝对令人惊讶。因此我自己采用了它,但后来我做了一些修改,所以这是我目前正在使用的代码。 它的优点是,它允许您根据需要绝对格式化服务URL,连接更多的参数。
// Replace the buildUrl method
buildUrl: function (request) {
var me = this,
url = me.getUrl(request);
var added = [];
for(var p in request.params)
{
if (url.indexOf('{' + p + '}') >= 0) {
url = url.replace('{' + p + '}', request.params[p]);
added.push(p);
}
}
for(var a in added)
{
delete request.params[added[a]];
}
// That's enough, but we lose the cache buster param (see bellow)
return url;
// If we want the cache buster param (_dc=...) to be added,
// we must call the superclass, which will read the url from
// the request.
request.url = url;
return Ext.data.proxy.Rest.superclass.buildUrl.apply(this, arguments);
}
通过这种方式,您可以使用&#34; / service / {param1} / {param2} /?abc = {param3} &#34;给出了一个&#34; request.params&#34;像
这样的对象{ &#34; param1&#34;:&#34; value1&#34;, &#34; param2&#34;:&#34; value2&#34;, &#34; param3&#34;:&#34; value3&#34; }
并且无需覆盖&#34; buildRequest&#34;方法,因为此处使用的任何参数都会从&#34; params&#34;中删除。对象,以后不会与查询字符串连接。
我希望这有帮助,欢迎任何评论!