On Nov 7, 2005, at 9:30 AM, Shalabh Chaturvedi wrote:

I'm trying to write Quixote applications that can be re-used easily. So I do not want to bind the PTL templates tightly with my site header, footer and other standard 'pieces' of a page. My current strategy is to use:

import pageui

def someview [html] ():
    pageui.header()

    ...

    pageui.footer()

And not include pageui.ptl in this package at all. The user of this app then has to create pageui.ptl and make sure it is in the pythonpath. This allows me (and others) to re-use the application with different headers, footers and such.

1. Is this a good approach?

I have been doing something very similar also, as I expect that anyone who has had to manage the building of non-trivial pages has also. I have been meaning to reply to this earlier, but my code is not ready for just posting, so I took a little time now to review what I had done, and write it up somewhat clearly.

One problem I see with what you propose is that what happens if an error occurs in teh middle of your view rendering? And, the page you wish to display uses a different visual style in that case.

I have a whole scheme, that tries to do a lot more than what you are after I think, by which a page_info object is constructed during page processing, and then rendering will cause that all (css, js) x (files, code snippets) will be conveniently placed in the head element, irrespective of where they have "sprung out" from within the page, making page easier to load, and debug...

2. Is there value in standardizing the 'pageui' API? For example I end up using not just header() and footer() but also msg_box(msg), link_button(label, target) and other such components.

I have also included info of how I handle rather complex page components, that have their own behaviour and interaction. These also know how to talk to the page_info object.

My current implementation, for quixote, is not as clean as the partial description in the attached file. As I will probably be revising it anyway, and possibly doing it for qp, I would appreciate any comments you may have, even suggestions of better names. I also would be happy to converge this with other similar efforts that may be going on... QP already has a very simple idiom for rendering a page, namely that publisher.page() renders by calling publisher.header() and publisher.footer(), that are therefore easily overridden by the site's publisher. What I describe is actually not very different, but more general i think. I'd also be interested of ideas of how best to add this onto qp... but ill take that to that list.

mario


# Idiom for building complex web pages
# Author: [EMAIL PROTECTED]

A description of an idiom for building complex web pages, that contain 
behaviour-rich page components. Note that this is independent of the templating 
being used.


# page_info ##################################################################

Each page has an info object, either defined wherever the page is defined, or 
in some centralized place, as preferred. A copy of this object is passed along 
to the request (or hit in qp) and it can be therefore modified freely during 
page processing, before rendering. 

A basic idea here was to maximize sanity when developing complex html pages, as 
well as making those complex pages as simple as they can possibly be, for the 
browser to handle, and for debugging. If all css and js required by a page is 
built in this way, then *all* of it is rendered in the page's <head>, that is 
therefore guaranteed to be all loaded by the time the page onload gets fired, 
thus shortcutting many potential annoyances. 

page_info = dict(

    '''
    We may want to have different "visual" categories of pages
    '''
    category = 'std', # 'home' | 'error' | 'data_listing' | ... 
    
    '''
    Some pages have a fixed title. This can be in and of itself a tiny 
    template, for variable substitution at page-rendering time.
    '''
    title = string, 
    
    '''
    css file names, each giving a <link rel="stylesheet"> element
    '''
    css_files = [], 
    
    '''
    css code snippets, inlined in a single <style> element
    '''
    css_codes = [], 

    '''
    js file names, each giving a <script src="..."> element
    '''
    js_files = [],  

    '''
    js code snippets, inlined in a single <script> element
    '''
    js_codes = [],  
    
    '''
    js code snippets that you want to be executed when the page is loaded.
    These are wrapped inside a function, e.g. page_onload(){}, and written
    out in the same <script> as for js_codes. Plus, if not empty, <body>      
    gets an onload="page_onload();" attribute.
    '''
    onload_actions = [], 

    '''
    Any attributes we may wish <body> to have. 
    '''
    body_attrs = dict, 
    
)


# pageui.py ##################################################################

In a separate module or modules, there will be a corresponding 
page/header/footer set of functions for each page category, that therefore 
calling:

    pageui.page(page_info, *contents, **kwargs)

will delegate calls to the appropriate functions for value of category, e.g. 
for an std page, the rendering will be the accumulated return values of:

    std_header(page_info, contents, kwargs)
    std_content(page_info, contents, kwargs)
    std_footer(page_info, contents, kwargs)


# page_components ############################################################

Page components are rather complex formatting objects, that may have behaviour, 
that may have their own content, that know nothing about forms and form widgets 
but have to play very nicely with any of them (they do not know if they contain 
widgets that belong to some form on the page, or whether they themselves 
contain a form in its entirety. Interaction with rest of page is key. 

Examples that I have made are CollapsableBox, TabbedSections, SortableTable, 
custom variations of these as well as others. 

Each page component instance has a prefix that must be unique within the page. 
It can then use this to derive however many names it needs, such as widget 
names, element ids, etc., not only without overstepping anything else on the 
page but also may expose these "internal" objects to others on the page.

I have a BasePageComponent class, with the constructor:

    def __init__(self, prefix='bpc', page_info=None, content=None):
    
Page components not only know how to render themselves, but also can generate 
specific bits of css and js that are added to page_info, as well as make sure 
that a special external css or js file that they need will be loaded by the 
page. 

Internally, they define their own "boilerplate" code, for html, js and css, and 
render it all as appropriate with page specific data. 


##############################################################################


_______________________________________________
Quixote-users mailing list
[email protected]
http://mail.mems-exchange.org/mailman/listinfo/quixote-users

Reply via email to