我正在尝试使用服务器端的django / tastypie和客户端的backbone / marionette为朋友构建订单系统。服务器端没有什么大问题,但由于我是一个没有经验的前端开发人员,我有点卡住了;
更简单的情况很好,例如使用Composite-和ItemViews列出,添加,编辑和删除文章(只是我的数据库中的一个表,包括sku,描述等)。问题是我正在尝试构建一个Order的视图,因为它包含几个表在服务器端有关系。
订单
LineItem的
文章
StoreQuantity
商店
StoreQuantity
商店
的LineItem
文章
StoreQuantity
商店
StoreQuantity
商店
...
因此订单包含多个LineItem。 LineItem由一个文章和几个StoreQuantity组成:s可以模拟诸如“订购商品A;商品X的10份和商店Y的4份副本,商品X;商店X的4份副本和商店Y的1份”
我想我的问题是;我将如何为上述内容构建我的观点?
下面的内容会是错误的吗?
创建一个OrderCompositeView并从我的控制器传递OrderModel。
从服务器获取OrderModel时,让OrderCompositeView创建一个LineItemCompositeView。
当LineItemCompositeView从服务器获取其'LineItemCollection时......依次递归
我是否应该创建一个REST-url,它返回Order的整个JSON及其关系,而不是几个较小的递归调用,然后尝试解析JSON客户端?
我找到了几个关于如何使用Marionette的好资源但没有关于如何处理嵌套多层深层数据的资源。
谢谢/马格努斯
编辑:
显示一些代码,说明我一直在测试的内容
(查看)
var LineItemDetailView = Backbone.Marionette.ItemView.extend({
template: "#lineitem-layout-template",
tagName: "div",
initialize: function() {
}
});
var LineItemView = Backbone.Marionette.CompositeView.extend({
template: "#lineitem-wrapper-template",
childView: LineItemDetailView,
childViewContainer: "div",
initialize: function(coll, obj) {
this.collection = new LineItemCollection({url: "api/v1/lineitem/?order__id=" + obj["order_id"]});
this.collection.fetch({
success: function() {
console.log("Successfully fetched lineitems");
}
});
}
});
var OrderDetailView = Backbone.Marionette.CompositeView.extend({
template: "#order-detail-template",
childView: LineItemView,
childViewContainer: "#lineitems",
initialize: function() {
this.model.on("sync", function(mod) {
lineitemView = new LineItemView([],{order_id: mod.get("id")});
});
}
});
这些方面的东西。 OrderDetailView是从我的控制器创建的并传递了OrderModel。我从这里得到OrderDetailView:s模板来渲染,LineItemCollection从服务器获取,但没有更多的事情发生。
答案 0 :(得分:0)
所以我在前几天创建应用程序的调查部分时遇到了这个问题。它有这样的结构: 调查: 题: 回答 回答 题: 回答 答案
非常类似于你正在做的事情。我使用骨干关系宝石 - http://backbonerelational.org/将模型联系在一起并且效果很好。我的API在一次调用中发送回所有JSON。所以survey / 1.json会带回所有上述部分/他们的数据。然后我用Backbone关系解析/分解它们。这是他们的样子:
调查:
class Entities.Survey extends App.Entities.Model
urlRoot: "surveys"
defaults:
status: "Draft"
number_taken: 0
survey_limit: 500
relations: [
type: Backbone.HasMany
key: "questions"
relatedModel: Entities.Question
reverseRelation:
key: 'survey'
includeInJSON: 'id'
]
问题:
class Entities.Question extends App.Entities.Model
urlRoot: "questions"
defaults:
single_response: true
terminate: false
free_text: false
relations: [
type: Backbone.HasMany
key: "answers"
relatedModel: Entities.Answer
reverseRelation:
key: 'question'
includeInJSON: 'id'
]
答案:
class Entities.Answer extends App.Entities.Model
urlRoot: "answers"
defaults:
branching: false
next_question_id: null
然后当你去显示它们时,在我的调查显示视图中,我有一个布局视图,其中有一个问题区域,它使用调查问题的复合视图,如下所示:
class Show.Controller extends App.Controllers.Application
initialize: (options) ->
{ survey, id } = options
survey or= App.request "survey:entity", id
App.execute "when:fetched", survey, =>
@layout = @getLayoutView()
@listenTo @layout, "show", =>
@panelRegion survey
@questionRegion survey
@bannerRegion survey
@show @layout
questionRegion: (survey) ->
App.request "show:survey:questions", survey, @layout.questionRegion
然后我进来得到问题:
questionRegion: (survey) ->
questions = survey.get('questions')
questionView = @getQuestionView questions, survey
问题的子视图CompositeView本身就是一个带有子视图答案的CompositeView。
所以Survey有一个问题CompositeView of Questions,每个都是一个复合视图的答案。
您应该可以在应用中遵循类似的结构。如果你被困在任何地方,请告诉我!
编辑:添加视图/控制器。
所以这就是我做的,当用户导航到某个路线时 - 比如localhost:3000 /#surveys / 1 /编辑它命中我的surveyrouter(注意一些代码,比如我删除的列表部分):
@TheoremReach.module "SurveysApp", (SurveysApp, App, Backbone, Marionette, $, _) ->
class SurveysApp.Router extends Marionette.AppRouter
appRoutes:
"surveys" : "list"
"surveys/:id" : "show"
"surveys/:id/take": "take"
API =
show: (id, survey) ->
new SurveysApp.Show.Controller
id: id
survey: survey
take: (id, survey) ->
new SurveysApp.Take.Controller
id: id
survey: survey
App.vent.on "survey:clicked", (survey) ->
App.navigate "surveys/" + survey.id
API.show survey.id, survey
App.vent.on "take:survey:button:clicked", (survey) ->
App.navigate "surveys/" + survey.id + "/take"
API.take survey.id, survey
App.addInitializer ->
new SurveysApp.Router
controller: API
所以我可以在导航或触发“调查:点击”事件时到达此处。然后创建我的节目控制器:
@TheoremReach.module "SurveysApp.Show", (Show, App, Backbone, Marionette, $, _) ->
class Show.Controller extends App.Controllers.Application
initialize: (options) ->
{ survey, id } = options
survey or= App.request "survey:entity", id
App.execute "when:fetched", survey, =>
@layout = @getLayoutView()
@listenTo @layout, "show", =>
@panelRegion survey
@questionRegion survey
@bannerRegion survey
@show @layout
questionRegion: (survey) ->
App.request "show:survey:questions", survey, @layout.questionRegion
panelRegion: (survey) ->
panelView = @getPanelView survey
@listenTo panelView, "new:question:clicked", (args) ->
question = App.request "new:question:entity"
model = args.model
model.get('questions').add(question)
question.set(survey_id: model.get('id'))
App.request "new:question:added"
@show panelView, region: @layout.panelRegion
bannerRegion: (survey) ->
bannerView = @getBannerView survey
@listenTo bannerView, "take:survey:button:clicked", (args) ->
App.vent.trigger "take:survey:button:clicked", args.model
@show bannerView, region: @layout.bannerRegion
getLayoutView: ->
new Show.Layout
getBannerView: (survey) ->
new Show.Banner
model: survey
getPanelView: (survey) ->
new Show.Panel
model: survey
这使得一个新的问题显示控制器(与上面相同的路由器案例处理"show:survey:questions"
请求并启动一个新的控制器,所以我将跳过该代码。)
@TheoremReach.module "QuestionsApp.Show", (Show, App, Backbone, Marionette, $, _) ->
class Show.Controller extends App.Controllers.Application
initialize: (options) ->
{ survey } = options
@layout = @getLayoutView()
@listenTo @layout, "show", =>
@questionRegion survey
@show @layout
questionRegion: (survey) ->
questions = survey.get('questions')
questionView = @getQuestionView questions, survey
App.reqres.setHandler "new:question:added", ->
questionView.render()
@show questionView, region: @layout.questionRegion
getLayoutView: ->
new Show.Layout
getQuestionView: (questions, survey) ->
new Show.Questions
collection: questions
model: survey
问题的标准复合视图:
class Show.Questions extends App.Views.CompositeView
template: "questions/show/_questions"
className: "questions"
itemViewContainer: ".editor"
itemView: Show.Question
然后每个问题都是一个复合视图:
class Show.Question extends App.Views.CompositeView
template: "questions/show/_question"
id: "1000"
className: "step"
initialize: ->
@collection = @model.get("answers")
@model.set(question_number: @model.collection.indexOf(@model) + 1)
if @model.get('free_text') and @model.get('answers').length < 1
answer = App.request "new:answer:entity"
answer.set(free_text: true, question: @model, title: @model.get('title'))
@collection.reset(answer, {silent: true})
@on "childview:answer:delete:clicked", (child, args) =>
args.collection = @model.get('answers')
@trigger "answer:delete:clicked", args
itemView: Show.Answer
itemViewContainer: ".answer-container"
它从骨干关系中的答案组中获取其集合。我会注意到,这可能只是一个布局,在初始化函数中,我应该向答案应用程序发送请求以获取答案列表并将其添加到答案区域。我还没有解决这个问题:)。