And I don't myself pretend to have *today* sufficient knowledge of Webware to be at the lead of a major move.
But then I must admit it is a vicious endless circle :
No concrete example or tutorial for beginners, insufficient docs => less people interested in Webware => less docs and tutorials because the other people have learned the hard way (OK not so hard we all love writing/reading python code) so they dont feel it necessary to write docs...
Just a simple example, that stunned me when I started with Webware: image servlets.
In PHP nothing is simpler than having a .php script returning a PNG image for use as source inside and HTML IMG tag => dynamicaly generated images. Googling on the subject returns tenth of pages of PHP+GD samples.
With webware the only actually working examples are found in *mailing lists*. There is not even one html page looking as a tutorial on the subject.
Now assuming that we use actual files for storing images instead of having them returned via content-type image/png.
Is it possible to have a per-user-session temporary directory under Sessions, where we would happily store all those temp images, and have the session handling engine automgically delete them on logout ?
docs => nothing google => nothing
Every example related to sessions in Webware is for storing values.
There is no documentation about doing your custom session store (and the cases where you'll need).
But I cannot say "you can't have a per-session temp dir" because it's not clearly stated => I end up reading the code again.
For people like me that like both python and the webware has having superior design and elegance over PHP, it's quite frustrating not being able to make the move from PHP to webware on bigger sites that our development servers : The management is afraid (with valid reasons) that it will be costly/hazardous to succeed making people having same/superior knowledge in this framework as in PHP.
Without the core developers / old warriors making the first move and feeding the community with better docs, most of the wanna-be-python-webware-hackers (like me today) will either stall at their current knowledge level, each using it's own custom and unique approach over and over again, or will resign and move to some more user-friendly framework.
Maybe the first steps could be :
- Have a site with "doc requests" like the feature requests often found for development.
- A kind of Webware Wiki/devcenter where everyone could contribute, like codeproject.com or codeguru.com for the Win32 guys (We run webware on Gentoo Linux but in my all-day work I have many parts to make in Win32/Windoz and these kind of sites prove to be valuable for providing examples on almost all common tasks you encouter in Win32 dev).
OFS.
Winston Wolff wrote:
I absolutely agree with your comments at the bottom about the state of web frameworks with python. It's not clear to me how to organize it to make it happen though, other than to keep stating it until everyone agrees.
Especially, I wish we had more Webware releases. I suppose I could just do it myself, but I feel I don't really know enough yet.
-ww
On Mar 10, 2005, at 2:38 PM, Olivier FAVRE-SIMON wrote:
For what it's worth I'm happy to share my way to use Cheetah with Webware. Comments are welcome.
Starting with some facts:
1. The only way to have powerfull but well-structured Cheetah templates is to use inheritance (#extends).
2. The only way to have FormKit (or any other form kit that rely on Webware actions) whitout manually tweaking original source code is to inherit from WebKit.Page
3. Cheetah.Template and WebKit.Page do not mix well (at least in current versions)
4. I don't like the "inheritance" approach described in the Cheetah User's Guide: I'm not a templar of the MVC church but a class hierarchy with logic and view classes being intermixed seems ugly and quite to me:
Template <--- SiteLogic.py <--- Site.tmpl/.py <--- PageLogic.py <--- Page.tmpl/.py <--- SecurePageLogic.py <--- LoginPageLogic.py <--- LoginPage.tmpl/.py
So I came to this design:
Since templates are single inheritance only (only one base class, with Template at the root), and I don't want intermixed logic/view classes, let's *** have 2 class hierarchies: one for logic, one for views *** :
WebKit.Page <-------------------+---SitePage.py <------+------ Main.py | | MiscUtils.Configurable <--+ +------ .... other public pages |
+------ SecurePage.py <-------+------ Login.py |
+------ Music.py |
+------ ... other 'login required' pages
SitePageView.tmpl <------+------ MainView.tmpl | +------ LoginView.tmpl | +------ MusicView.tmpl
Each Page in the site will instantiate the corresponding View as self.tmpl in its __init__() method.
The .py View has been previously generated from the .tmpl via "cheetah compile" and a Makefile.
The searchList is [self], so the template can access all attributes the same way it's done in the documented "inheritance approach".
The SitePage class defines 2 methods that subclasses may override: - get_data() to gather all page data (i.e. the controler / business logic) : Obviously must be redefined because each page has a different content - write_html() to generate page content (i.e. the view) : Most a the time the default is sufficient : write the HTML via str(self.tmpl)
Because all pages are Webkit pages rather than Cheetah templates it is possible to use FormKit for the Login page and let Webware actions handle the form.
==================================================== class SitePage(Page, Configurable):
def __init__(self):
Page.__init__(self) Configurable.__init__(self)
from SitePageView import SitePageView self.tmpl = SitePageView(searchList=[self])
def writeHTML(self):
self.get_data() self.write_html()
def write_html(self):
self.writeln(str(self.tmpl))
### etc. other SitePage methods ###
==================================================== class SecurePage(SitePage):
def __init__(self): SitePage.__init__(self)
def awake(self, trans): SitePage.awake(self,trans) # pseudo-code here: use session() + database query to check login data if ## session invalid / expired## : trans.response().sendRedirect('Login')
### etc. other SecurePage methods ###
==================================================== class Login(FormKitMixIn, SecurePage):
def __init__(self):
SecurePage.__init__(self)
f = self.form = Form.Form(validators=[PasswordValidator(self)])
self.addForm( f )
f.addField( Fields.TextField('username', [Validators.MinLength(5)])) f.addField( Fields.PasswordField('password', [Validators.NotEmpty()])) f.addField( Fields.WebKitSubmitButton(name="submit", label="Log in"))
from LoginView import LoginView self.tmpl = LoginView(searchList=[self])
def get_data(self):
SecurePage.get_data(self)
self.login_form_html = self.form.dump() #login_form_html is a place holder for the whole form in LoginView.tmpl
if not self.form.isSuccessful() and self.form.error(): # add form error msg self.login_form_html = self.login_form_html + '<p style="color:red;">%s</p>' % self.form.error()
def actions(self): """Form actions - standard WebKit stuff""" return ['submit']
def submit(self): """action for submit button : save user info and redirect to requested page (default: Main) if login successful."""
if self.form.isSuccessful(): self.session().setValue('user', self.userid) self.session().setValue('username', self.form.username)
self.response().sendRedirect(self.request().field('page', 'Main'))
### etc. other Login methods ###
==================================================== class Music(SecurePage):
def __init__(self):
SecurePage.__init__(self)
from MusicView import MusicView self.tmpl = MusicView(searchList=[self])
def get_data(self): '''A simple pusic page for the example: display all songs that starts with a given letter in a music files directory.''' SecurePage.get_data(self) self.letter = self.request().field('letter','A') DIR = '/mnt/disk/music' from string import upper from path import path d = path(DIR) self.music_files = [i.name for i in d.listdir() if upper(i.name).startswith(upper(self.letter))] #music_files is a place holder for MusicView.tmpl, wich will iterate (e.g. #for $f in $music_files) to display
### etc. other Music methods ###
To make it short what is needed for a new page is:
1. Instantiate the correct view in __init__() 2. Override get_data() to generate content 3. Provide the template for the view
On the negative side, the views must have been previously generated from the .tmpl via "cheetah compile"; I've not found a way to have a servlet instantiated template being dynamically compiled when it #extends another template.
With the help of a little Makefile:
VIEWS=SitePageView.py LoginView.py MusicView.py
..SUFFIXES: .py .tmpl
all: $(VIEWS)
LoginView.tmpl: SitePageView.py Login.py: LoginView.py
MusicView.tmpl: SitePageView.py Music.py: MusicView.py
clean: rm -f *.pyc rm -f *.py.bak rm -f $(VIEWS)
..PHONY: all clean
..tmpl.py: @cheetah compile $<
I've been using python for some time now, mainly for PyGTK desktop GUI's or XMLRPC/SOAP web services, but for pure web development I'm coming from a PHP/Smarty background.
PHP is good for rapid prototyping but on the long-term it's all spaghetti code with screens "pulling" the data from databases. Rails is really cool but it's Ruby ;-)
I'ts a pity for me to see that python (IMHO the best language whatever the domain you're working in) has 10 or so web frameworks with as many template engines. That's too many brainpower dissipated in duplicate endeavours. PHP and Rails are strong because the whole community agreed that choosing a "main" (in not single) framework was more important than any technical argument/point of view/limitation/whatever.
If we want python to *really* make it on web servers (I mean as an opensource initiative, not Zope), the only way to succeed is (by priority order):
1. Stop/refrain from developping new features when the existing codebase is so poorly documented. (Microsoft MFC and .NET are crap but the documentation is really impressing and make it possible to start from scratch in very little time)
2. Add many examples and a real tutorial. What I mean is that one must not have to copy/paste from html pages to have a running tutorial site. We should have say a webware-examples.tar.bz2: just unpack it in some /opt or /var/www directory, tweak httpd.conf a little and it must be running from scratch).
3. Clearly an non-ambiguously define which packages are prefered and which are deprecated: e.g. Many people advocate SQLObject for Rails-alike sites (which I agree), but nowhere is it clearly defined that one must choose SQLObject over MiddleKit, say for new sites. e.g. I completely failed to understand what UserKit is meant for and how to use it; googling about it did not return valuable info or a good example.
4. Release early release often: The only thing that stops me to actually put big Webware sites on the corporate servers in the company i'm working for is seeing that same 0.8.1 version for so long. I know that development is still going on: I'm regularly updating my development box from [EMAIL PROTECTED] webware module but any serious management will throw me away if I ever speak of a CVS version on a prod server (even a tiny one).
Trust matters, and the best way to ensure trust is to *show* that things evolve; knowing it is not sufficient.
What we need is JOINING FORCES (and not only in Webware+Cheetah; other web frameworks (heho Aquarium) have common needs/requirements: form handling, session management, etc.
Regards.
OFS.
_________________________________________
winston wolff - (646) 827-2242 - http://www.stratolab.com - learning by creating
signature.asc
Description: OpenPGP digital signature