On 7/13/09 7:59 AM, Alberto Valverde wrote:
> Hello,
>
> I'm factoring out the core logic of a bunch of views into a generic CRUD
> "controller" for a bfg app which looks something like this:
>
> class GenericCrud(..):
>      def __init__(self, bunch of configuration options):
>          # update __dict__ with these options and some derived ones
>
>      def member_view(self, context, request):
>          # dispatch to helper method on HTTP method
>
>      def collection_view(self, context, request):
>          # ditto
>
>      # collection_view dispatches to this on POST
>      def create(self, context, request):
>         # just a normal view function but have settings and helper (quite
> possibly overridden)
>         # methods accessible at 'self'. The instance is *never* modified here
>
>      # member_view to this on PUT
>      def update(...): ...
>
> which is used like this:
>
> # some_views.py, module scope:
> class UserCrud(GenericCrud):
>      # some template methods implemented
>
> # Instantiate a module-scope (stateless) singleton
> user_crud = UserCrud(some overrides like grid columns, form fields, etc...)
>
> # Now the work-arounds so the views can be registered I'd like to get
> rid of,
> # I'll explain below.
> user_member_view = user_crud.member_view
> user_collection_view = user_crud.collection_view
>
> This is wired up into the ZCA registry like this, configure.zcml:
>
>    <view
>       for=".interfaces.IUsers"
>       view=".views.user.user_config_view"
>       name="config.js"
>       permission="view"
>       />
>    <view
>       for=".interfaces.IUsers"
>       view=".views.user.user_collection_view"
>       request_type="GET"
>       permission="view"
>       />
>    <view
>       for=".interfaces.IUsers"
>       view=".views.user.user_collection_view"
>       request_type="POST"
>       permission="create"
>       />
>    <view
>       for=".interfaces.IUser"
>       view=".views.user.user_member_view"
>       request_type="GET"
>       permission="view"
>       />
>    <view
>       for=".interfaces.IUser"
>       view=".views.user.user_member_view"
>       request_type="PUT"
>       permission="update"
>       />
>    <view
>       for=".interfaces.IUser"
>       view=".views.user.user_member_view"
>       request_type="DELETE"
>       permission="delete"
>       />
>
> Ok, the above zcml sucks a bit right now in the terseness department
> since there needs to be a directive for each request_type just to
> declare permissions (it wouldn't be needed otherwise since the
> "controller" takes care of dispatching) but I'll eventually write my
> custom zcml directive-processors which will take care of the
> bolier-plate when I find some time to learn how-to.

Right.

>
> Anyway, I'd like to remove the work-arounds I mentioned (the user_*_view
> aliases at module-scope) since the "view" directive doesn't seem able to
> import an instancemethod (or any non-module-global for that matter, I
> think).

Yes, the resolver won't descend past module scope to find names.

> They're not too bad at the moment but it will soon be when I
> wire up all the exposed domain models....
>
> Would this be possible or even desirable? Is there a better pattern to
> do this kind of "pre-configured" views that someone can share? I'd
> happily send a patch for this with tests, just point me in the right
> direction (I'm still mapping the repoze.* namespace in my head...).

I'm not sure if this helps, but instead of making a view out of an 
instancemethod with a special name, maybe you could make N view classes, one 
for 
each alias you currently have:

class UserCrud(GenericCrud):
     def __init__(self, context, request):
         self.context = context
         self.request = request

class UserMemberView(UserCrud):
     def __call__(self):
         ... do member-related dispatching ...
         ... return response ..

class UserCollectionView(UserCrud):
     def __call__(self):
         ... do collection-related dispatching ...
         ... return response ..

then in ZCML:


     <view
        for=".interfaces.IUsers"
        view=".views.user.UserCollectionView"
        request_type="GET"
        permission="view"
        />

     <view
        for=".interfaces.IUsers"
        view=".views.user.UserCollectionView"
        request_type="POST"
        permission="create"
        />

     <view
        for=".interfaces.IUser"
        view=".views.user.UserMemberView"
        request_type="GET"
        permission="view"
        />

     <view
        for=".interfaces.IUser"
        view=".views.user.UserMemberView"
        request_type="PUT"
        permission="update"
        />

     <view
        for=".interfaces.IUser"
        view=".views.user.UserMemberView"
        request_type="DELETE"
        permission="delete"
        />

> I've already evaluated using a class as a view [1] but having the

Aw you left us hanging.

> PS: I'm having *a lot* of fun with bfg! Big thanks for extracting all
> these zope gems (and the non-zope ones you've created) into easily
> digestible eggs for the rest of us. :)

Thanks for the feedback!

- C
_______________________________________________
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev

Reply via email to