Google Groups

Re: Architecture of a backbone+pyramid single page app


Sontek Feb 23, 2012 11:02 AM
Posted in group: pylons-discuss


On Thu, Feb 23, 2012 at 1:01 PM, John Anderson <son...@gmail.com> wrote:


On Thu, Feb 23, 2012 at 3:47 AM, tonthon <tont...@gmail.com> wrote:
Hi all,

I'm looking for some feedback on building a single page app with backbone and pyramid (I'm using Sqlalchemy as ORM).

How do you handle Urls on the js side ?
How do you handle form submission (I like deform but it doesn't seem to fit my needs here) ?

Cheers,

Gaston


For URLs I just define a convention and use that everywhere.  But you have to tell Pyramid to not handle those requests, so I have the following:

def automore(request, elements, kw):
    # this is for adding the more kwargs for backbone urls
    kw.setdefault('more', ())
    return elements, kw

config.add_route('index', '/*more', pregenerator=automore)


This tells pyramid to send all requests to the index route, we do this because backbone.js is actually going to handle the routing.

Then for form submission I actually build RESTful webservices in pyramid and on form submit I pass my form data to a backbone model and then save that out, and use colander to actually validate the data coming in:

        map_form_to_model: function(data, model) {
            model.off("change");

            for(var i=0; i < data.length; i++) {
                var name = data[i].name;
                var value = data[i].value;

                var current_value = model.get(name);

                if (value != current_value) {
                    model.set(name, value);
                }
            }
        },

            save_model: function(e) {
                e.preventDefault();

                if (this.model != undefined) {
                    var me = this;

                    var data = me.$("form").serializeArray();
                    map_form_to_model(data, me.model);

                    me.model.save({
                        error: function(e) {
                            console.log(e);
                        }
                    })
                }
            },



and the server side of something like that:

    @json_result
    def get_user(self):
        user = None

        try:
            pk = self.request.matchdict.get("user_pk")
            user = self.manager.get_by_pk(pk)
        except DataError:
            pass

        if not user:
            return HTTPNotFound()

        return user.serialize()

    @json_result
    def save_user(self):
        data = json.loads(self.request.body)
        schema = ProfileSchema()

        try:
            cstruct = schema.deserialize(data)
        except colander.Invalid, e:
            return HTTPBadRequest(e.asdict())

        try:
            pk = self.request.matchdict.get("user_pk")
            user = self.manager.get_by_pk(pk)
        except DataError:
            pass

        if not user:
            return HTTPNotFound()

        map_dict_to_obj(cstruct, user)

        self.db.add(user)

        return {'success': True}




Also, for security I do everything off an API key and send it with every ajax request:

    $(document).ajaxSend(function(event, xhr, settings) {
        var user = EventQ.get_user();

        if (user == null) {
            return;
        }

        if (user != undefined || user != 'undefined') {
            xhr.setRequestHeader("X-EventQ-Key", user.api_key);
        }
    });