On Tue, 2011-02-01 at 10:42 +0100, Stéphane Klein wrote: > Le 31/01/2011 17:42, Jim Washington a écrit : > > ZODB + Pyramid + Pyjamas + PureMVC. > > I'm curious about "Pyjamas + PureMVC". Can you say more about your > utilization of this tools ? > > Thanks for your feedback.
Hi, Stéphane I presume you ask three questions: Pyramid + Pyjamas Pyramid + JSON-RPC (server communication for Pyjamas) Pyjamas + PureMVC (PureMVC in Pyjamas on the client side) Apologies for the length of this message. Disclaimer: I am a Pyjamas developer, and I am posting this partly because we can always use more smart and able developers using and contributing to the project, and providing easy usage methodology helps with that idea. Pyjamas: http://pyjs.org (use the git repository): I use Pyjamas because my application is very dynamic. There are a lot of widgets, and a lot of data updates, and I can update the data in any particular widget without refreshing the entire page. Plus, my Pyjamas code is all python. Python on the server + Python on the client = bliss. The application feels very application-like instead of web-page-like, but I can use css for styling and widget placement. Pyjamas is very easy to use with Pyramid. Each Pyjamas app just needs to reside somewhere static: e.g., static/app1/App1.html I set the --output to that directory for the pyjsbuild command in the Pyjamas app's build.sh file. I let nginx or apache serve static. JSON-RPC: Pyjamas uses JSON-RPC for communication with the server. The following can probably be adapted for any JSON-RPC client, and maybe for non-ZODB models. For JSON-RPC on the server side, I use lovely.jsonrpc. from lovely.jsonrpc import JSONRPCDispatcher For any ZODB location I wish to directly access without special permissions, I set a view config in my Pyramid app's views.py: @view_config(context="myapp.models.MyClass", request_method="POST") def my_class_rpc(request): body=request.body context = request.context resp = JSONRPCDispatcher(context).dispatch(body) # resp is the JSON-RPC response for the context's method. # Fail if the method returns something that is # not representable in JSON. r = Response(resp, content_type='application/json') r.cache_control = 'no-cache' r.pragma = 'no-cache' return r The above allows all methods in any MyClass object to the client's JSON-RPC implementation. This simplifies operations while developing the app. Client's JSONProxy uses http:// mySite/path/to/object as its url. If I want different methods and permissions for the view, I make a view class: class MySpecialView(object): """do something silly""" def __init__(self, context): self.context = context def _private_method(self, param): resp = self.context.twiddle_param(param) # context returns something JSON-representable return resp def some_method(self, some_param): intermediate, OK = self.context.safe_method(some_param) if not OK: return self._private_method(intermediate) return intermediate And then my view config looks like: @view_config(context="myapp.models.MyClass", request_method="POST", permission="some.permission") def my_class_rpc(request): body=request.body context = MySpecialView(request.context) resp = JSONRPCDispatcher(context).dispatch(body) r = Response(resp, content_type='application/json') r.cache_control = 'no-cache' r.pragma = 'no-cache' return r In this case, JSON-RPC from the client only has MySpecialView.some_method available to use. If I wanted to use "Zope Component Architecture", MySpecialView would be an adapter. If I want the request url to end in something other than '/': the view_config can look like @view_config("jsonrpc", context="myapp.models.MyClass", request_method="POST", permission="some.permission") and the client's JSONProxy's url would be http://my_site/path/to/object/jsonrpc PureMVC : http://puremvc.org PureMVC has a pure python implementation, which imports into Pyjamas without any trouble. See the Pyjamas EmployeeAdmin example within the Pyjamas source for example usage. I use PureMVC as an organizational tool for developing the client-side app, and its notification (event) oriented nature simplifies between-widget and app-to-server coordination. It also reduces the potential for circular imports, which Pyjamas does not handle well. I had a jargon hurdle to overcome with PureMVC, but my understanding of it is as follows: For PureMVC, I work with five modules, "components", "controller", "consts", "model", and "view". These may be split up into sub-modules, and may be enhanced with objects from other modules, but for simplicity, I will refer only to these five modules. The objects in the "view", "model", and "controller" modules are registered and looked up by name, which is a string. Notifications are also named as strings, but ordinarily are held in the "consts" module to reduce the possibility of typographical errors in my code. For the following, when I refer to "view" objects, they are actually "Mediator" objects, and when I refer to "model" objects, they are actually "Proxy" objects. Methods in the "controller" are actually "Command" objects. Forget that jargon for the moment. I simplify a bit in the following. The "components" module has the Pyjamas application, with all of its ui widgets. The "view" module has objects that can listen for "onXXX" events belonging to particular widgets within the app. A "view" object's "onRegister" method sets up the listeners for the widget's "onXXX" methods. When the "view" object hears an event, it can send notifications for other "view" objects or "controller" methods, and can call methods on "model" objects. "View" objects also listen for particular notifications sent by other "view" objects, "model" objects, and "controller" methods, so that the widget in the app can be queried or updated. The "model" module holds the business data. The objects here can communicate with the server and send notifications for "view" objects or "controller" methods to handle. For example, when data is received from the server, a notification may be sent. The "controller" module holds methods that are invoked upon notification. These methods can send notifications, and can call methods on objects in the "model" and "view" modules. The app itself can be pretty dumb, and is unaware that it is used in a PureMVC system. It may be developed separately, and the PureMVC system can be "bolted on" later. The above sounds complicated, but at least I did not throw "Command" , "Proxy", and "Mediator" around to confuse the description. :) Maybe a data path will help explain how PureMVC simplifies things. Here is a sample data path through a PureMVC pyjamas app: o User clicks a button in the app. o The app may directly handle the onClick event with some visual cue. o A "view" object also handles the onClick event by looking up a particular "model" object by name and calling a method on that object with some data. The data may come from a different widget in the app, and may be requested from that widget's "view" object, which can ask the widget for the data. o The "model" object has a method that makes a JSON-RPC call to the server with the data as a parameter. o When the server responds, the "model" object stores the data and sends a notification that new data has been received. The data may be sent as part of the notification. o Any "controller" method or "view" object listening for that notification handles the "model" object's notification appropriately, by updating widgets in the app and maybe sending additional notifications. I probably have a few details a bit wrong, but hopefully the general idea is understandable. - Jim Washington -- You received this message because you are subscribed to the Google Groups "pylons-devel" group. To post to this group, send email to pylons-devel@googlegroups.com. To unsubscribe from this group, send email to pylons-devel+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-devel?hl=en.