[Twisted-web] Livepage, ClientHandle and context

Alexey Shamrin shamrin at gmail.com
Mon Jun 6 10:24:51 MDT 2005


Hello!

Thank you for good explanations! As far as I can see you have already
commited good docstrings and backward-compatibility code into your
branch (r1545). It looks good!

On 6/2/05, Donovan Preston <dp at ulaluma.com> wrote:
> I also need to know how people want to use LivePage, 
> and if it has any usability shortcomings with this new 
> design which I describe below.

As you ask to describe how people use LivePage, here is my small example.

In a smaill project I am doing I use LivePage as follows (simplified
extract from the working code -- I haven't tested it...):

# example.py
from nevow import loaders, livepage, rend, tags as T

def get_teachers_list():
     # some code that returns the list of teachers goes here
     pass

class Editor(rend.Page):
    """Base class providing template for all pages"""
    addSlash=True

    docFactory = loaders.stan(T.html[T.body[T.directive('main_area')]])

class TeachersEditor(Editor,livepage.LivePage):
    """This page is exposed to the web"""

    def render_main_area(self, ctx, data):
        return livepage.glue, TeachersList(get_teachers_list())

class TeachersList(rend.Fragment):
    docFactory = loaders.stan([
        T.ul(render=rend.sequence, id='teachers_list')[
                T.li(pattern='item', render=T.directive('teacher_item'))[
                    T.a(render=T.directive('teacher_link'), href='#')[
                        T.slot(name='teacher_name')]]],
        T.div(id='teacher_details')])

    def render_teacher_item(self, ctx, teacher):
        return ctx.tag(id='teacher_%d' % teacher.id)

    def render_teacher_link(self, ctx, teacher):
        @livepage.handler
        def show_teacher(client):
            client.set('teacher_details',TeacherDetails(teacher))

        ctx.fillSlots('teacher_name', teacher.name)
        return ctx.tag(onclick=show_teacher, id='teacher_link_%d' % teacher.id)

class TeacherDetails(rend.Fragment):
      # this rend.Fragment also has @livepage.handler-ed closures
      pass

# end of example.py

As you can see, I use LivePage from inside rend.Fragment's subclasses
(TeacherDetails and TeachersList). But only the main rend.Page
subclass (TeacherEditor) is a subclass of livepage.LivePage. I also
use livepage.handler's as closures (TeachersList.render_teacher_link).

There were two problems with your branch and my code:

1. Backward compatible code didn't work for me (I don't remember what
was the reason. If you need details, I can make a better, working,
example.).

2. I tried to use new LivePage api, but I couldn't figure out how to
translate my code using it. For example, your ClientHandler.transient
seems to provide the ability to make browser-callable functions as
closures, but I am confused about the limitation of one-time calling.
Is it really necessary for a solution of garbage problem you mention?

I also can't see a way to use handler_* methods, because this methods
must be inside a rend.Fragment subclass in my case.

How can use the new api in my application?

> 2. I think you should have "nevow_" prefix for all things in liveglue.js.
> I agree, except I think I want the new "server" object to keep that name. It
> will be much easier for people to understand and use livepage if they know
> that calling server.handle('foo') in javascript invokes the handle_foo
> method on the server. Are there other things in there that aren't prefixed
> with nevow_?

Lot's of them. Just look inside liveglue.js... createRequest, connect,
auto_load, listener etc.

Or you can you preuso object-oriented approach like in Prototype
(http://prototype.conio.net/) or dojo.

> I have an incredible LivePage app I wrote recently I am calling "Pavel". I
> will be cleaning it up soon and I will create a new open source project for
> it (rather than including it as a nevow example). I think it really
> showcases the power of LivePage and I'm excited to show it to people, but
> for now it is somewhat of a secret :-)

I am looking forward for that!

> So if you were sending the following:
> 
> client.send([
> ��� livepage.alert('hello'),
> ��� livepage.set('name', 'Donovan Preston')])
> 
> You would need to terminate each statement, otherwise the javascript won't
> be correct. The above example would render as:
> 
> alert('hello')set('name', 'Donovan Preston')
> 
> Right now, you need to do:
> 
> client.send([
> ��� livepage.alert('hello'), livepage.eol,
> ��� livepage.set('name', 'Donovan Preston')])
> 
> Which will render down to:
> 
> alert('hello')
> set('name', 'Donovan Preston')
> 
> It occurs to me that it may be possible for Nevow to just infer that a
> newline is required between each element of a list or a tuple while in
> JavascriptContext. I will have to experiment and see whether this causes
> any�inadvertent problems. If not, the requirement to manually insert newline
> characters will go away (horray!)

I am not sure, but may be something like livepage.do would do the job
a little better?

client.send(livepage.do[
    livepage.alert('hello'),
    livepage.set('name', 'Donovan Preston')])

(or even livepage.progn...)

-- 
Alexey


More information about the Twisted-web mailing list