collective / rapido.core

2 stars 2 forks source link

not obvious to control block execution (on_display/on_init) #21

Open djay opened 8 years ago

djay commented 8 years ago

User problem

Currently a block works like this.

  1. If there is a action.blah in the request - execute that. If its a redirect then redirect
  2. else render the template
  3. execute each element as its reached in the template

There are a range of issues with this

Handles this by making making the python callable always the first thing called. It then produces a dict and that gets passed to the a template. but alternatively you can return whatever you want.

plone browserviews

These are classes that have an init method that always gets called with context and request. There is also the call method you can override.

Options

controller function

Make it such that you can have controller function that can direct or return custom content without the need of templates or elements.

def on_init(context):
   # tuple or list lets you create a simple response
   return ("text/xml","<mycustom>response</mycustom")

or

def on_init(context):
   context.mime_type = 'text/xml'
   return "<mycustom>response</mycustom"

or it will accept a zope response

def on_init(context):
   return context.request.response

or a file

def on_init(context):
   return StringIO("stream my response")

If you want to redirect then do

def on_init(context):
   return context.redirect = "./myotherblock"

but if its a dict (or None) it will look the template and use that.

def on_init(context):
    return dict(element1="blah", element2="something else")

and these can be used directly in a zpt (no more using ${elements/element1})

<html><body>${element1}</body></html>
ebrehault commented 8 years ago

Sorry I haven't told, but I have implemented it last week (I named it on_display instead of on_open), see https://github.com/plomino/rapido.core/commit/2f88bf52ee97583050eec01801b243c37aecfbed (If it matches your needs, just close the issue).

djay commented 8 years ago

Cool!. I think it would be good to consider some of the other ideas as well. Like controling the record and being able to insert things into the context and template.

ebrehault commented 8 years ago

It does it already:

Test it a little bit, if you think there is something missing, tell me.

djay commented 8 years ago

@ebrehault working on a patch now to show my ideas. The idea is instead of just on display it gets called on request and first. In the simplest case you can have no elements or template, just a single function called on_init or on_open or similar.

def on_init(context):
   # tuple or list lets you create a simple response
   return ("text/xml","<mycustom>response</mycustom")

or it will accept a zope response

def on_init(context):
   return context.request.response

or a file

def on_init(context):
   return StringIO("stream my response")

to it consistent with actions I think returning a string should redirect.

def on_init(context):
   return "./myotherblock"

but if its a dict (or None) it will look the template and use that.

def on_init(context):
    return dict(element1="blah", element2="something else")

and these can be used directly in a zpt (no more elements dict)

<html><body>${element1}</body></html>

These would be combined with any defined elements. The dict items returned from on_init would take precedence.

Anything else returned from on_init would give an error.