Python pages is a framework that makes it easier to develop web applications in Python. What is actually does is:
- Provide an easy way to embed Python code into HTML, similar to PHP, JSP and other server side languages.
- Cross platform: runs on Mac, Windows and Linux
- Aims to be as declarative as possible. But the Python language is always available to do the same.
- Standards compliant:
- XHTML strict output (forced through the framework)
- Correct use of HTTP status codes
- Unicode support
- Make reusing HTML very easy. It uses concepts like master pages and inclusion of other pages as a web control. This is a very rich template mechanism.
- when pages act like web controls for other pages, they are simply available as a member variable of the other pages.
- It contains a built-in HTTP/1.1 web server but supports CGI.
- Uses clean URLs. There are no .page extensions, and suffixes are available as a variable. For instance, if there's a page /test.page, then the URL /test/abc will render /test.page, but pass the suffix /abc. This is totally not a new concept, but just very easy to use.
- Output filters for post processing of the generated XHTML tree.
- URLs will always be relative to the page where they've been generated. This makes it very easy for included pages to use URLs relative to their own even if they are in a totally different directory. (This mechanism requires an output filter.)
The framework does not yet run in IronPython, but the IPy team will hopefully fix it soon.
When Python 3000 will be released, this framework will also be ported to Python 3000, and we'll stop supporting earlier versions as well.
The core (or render engine) is stable and working very well. However, there are still a few other parts of the framework that can be improved. (like the documentation)
Interested in contributing to the framework? Please contact me. We certainly can use some additional developers.
In the future
Some things we are working on:
- The render engine has built-in debug functionality. The current web based debugger isn't yet ready to use, but most of the back-end is already implemented. It should be possible to add or remove breakpoints while debugging and viewing the locals/globals.
- We will keep adding more web controls (like a forum, guestbook, ...)
- FastCGI support
Examples
NOTE: this examples are outdated and cannot be used anymore in this way. I have to rewrite them, but still, you get an idea of some possibilities.
A master page
<%!page output="xhtml" filters="resolve_uris,highlight_code" %>
<%!content name="Main" %>
<html>
<head>
<%!placeholder name="head" %>
</head>
<body>
<%!placeholder name="content" %>
</body>
</html>A 'child' using this master
<%!page master="/Master" external="true" %>
<%!content name="head" %>
<title>Hello world page</title>
<%!content name="content" %>
<p>
Let's count to 10:
</p>
<ul>
<% for i in range(0,10): %>
<li><%= i %></li>
<% endfor; %>
</ul>
<%
def factorial(i):
if i == 0:
return 1;
else:
return i * factorial(i - 1);
endif;
enddef;
%>
<p>
The factorial of 10 is <%= factorial(10) %>
</p>Silverlight control example
<%!page master="/controls/silverlight-xap" external="true" %>
<%!content name="python" %>
from System.Windows import Application
from System.Windows.Controls import Canvas
xaml = Application.Current.LoadRootVisual(Canvas(), "app.xaml")
xaml.textblock.Text = 'Hello world from IronPython'
<%!content name="xaml" %>
<Canvas x:Class="System.Windows.Controls.Canvas"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="parentCanvas">
<TextBlock x:Name="textblock" FontSize="30">Hello world from XAML </TextBlock>
</Canvas>Pages as controls (input fields are simply other pages):
<%!page master="/Master" external="true" %>
<%
if page.submit.has_been_submitted:
(page.f1.value, page.f2.value) = (page.f2.value, page.f1.value);
endif;
%>
<%!content name="title" %>
Input field test
<%!content name="content" %>
<form method="post">
<fieldset>
<legend>Submitting this form will switch the input fields' values</legend>
<%~f1:"/input/text" name="field1" label="Field 1"%>
<%~f2:"/input/text" name="field2" label="Field 2"%>
<%~submit:"/input/submit" value="Switch field values" %>
</fieldset>
</form>