Architecture of a backbone+pyramid single page app

339 views
Skip to first unread message

tonthon

unread,
Feb 23, 2012, 4:47:02 AM2/23/12
to pylons-discuss
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

--
TJEBBES Gaston
Majerti
http://www.majerti.Fr
+33 (0)6 32 70 70 00
+33 (0)4 27 78 88 99


John Anderson

unread,
Feb 23, 2012, 2:01:02 PM2/23/12
to pylons-...@googlegroups.com
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}



 

John Anderson

unread,
Feb 23, 2012, 2:02:41 PM2/23/12
to pylons-...@googlegroups.com
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);
        }
    });



Jonathan Vanasco

unread,
Feb 23, 2012, 7:54:34 PM2/23/12
to pylons-discuss
here's an example of the method i use...

https://gist.github.com/1896363

it's tailored to using jquery, but not hard to change.

1. i set everything to have an 'rval' that will return - at the least
- an error or success note.

2. i keep everything in a versioned API . these views map to "/api/
internal/v1/".

3. i prefer formencode . i released pyramid_formencode_classic, which
emulates a lot of the behaviors of how formhandling was done in pylons
( with a few improvements that make stuff faster for me )
Reply all
Reply to author
Forward
0 new messages