Big up to Termitnjak for organizing the amazing Zidanca sprint held last week. The venue for our get-together in south-eastern Slovenia was one of the most beautiful place I've ever sprinted at. Despite that and the gallons of fine wine that were poured, we still managed to get quite a few things done. Here is a summary.
Vanč <ferewuz> worked on upgrading Kotti's WISYWIG editor TinyMCE to version 4.0.2. This new version features a much nicer looking user interface, which fits a lot better into the overall Kotti style. It also works better with smaller displays, as the editor will now scale down along with the browser window's width. Our existing image-upload and document-linking pop-ups were updated to work with the new version. You can test drive on our demo site.
Natan <nightmarebadger> worked on adding tabbed forms support to deform_bootstrap. With this change, each nested (Mapping)Schema in your Colander schema will be rendered inside its own tab. As an example, consider this Client schema:
import colander class Person(colander.Schema): name = colander.SchemaNode( colander.String(), title='Name', ) class Car(colander.Schema): horsepower = colander.SchemaNode( colander.Integer(), title='Horsepower', ) class Client(colander.Schema): person = Person(title='Person data') car = Car(title='Car stuffs')
A deform_bootstrap form using the Client schema will render with two tabs 'Person data' and 'Car stuffs'.
kotti_multilingual was started by Andreas <disko> earlier this year. It includes basic support for language roots and switching between languages. The sprinters decided to use this package as the starting point for adding more advanced content translation support.
Before getting down to coding, we first had a round of discussion with Domen <iElectric>, Ramon <bloodbare>, Jure <ibi> and me. In particular, we discussed how plone.multilingual handles translations and 'language independent fields' and compared it to the venerable LinguaPlone. We decided that we'd use the LinguaPlone model, where translations derive from a so-called canonical document. This is the only document that holds the actual data for any of the language independent fields, and where all translated documents refer to when they look up those fields.
This is still a work in progress, but so far we've managed to h̶a̶c̶k̶ convince SQLAlchemy to return the value of a language independent attribute from the canonical document, if it exists.
We've also implemented linking between translations using a separate translations table. This, too, works quite similar to how LinguaPlone does it when you configure it to use one root folder per language (e.g. /en, /de, and so on). For locating the destination folder for new translations, we look up the parent document's translation, and put the new translation in there. Thus, a translation from /en/food/mexican will automagically be created at /de/food/mexican, given that /de/food is already a translation of /en/food.
Andreas pointed us to the SQLAlchmey Versioned Objects example. He had used it in a Pyramid project and it worked very well for him. So Vanč took this up on the last day of the sprint and implemented a prototype for history support for Kotti.
Vanč reports that his prototype saves the old version of a document anytime you edit it, and keeps all the old versions. Next on his list is adding a user interface for viewing older versions (there's merely a list right now), and adding options for deciding which content types to version and how many old versions to keep. Other things to work on are a separate button for when you want to save a new version, so that small changes can be made without creating a new version. And possibly a comment field to describe what the changes in your new version are about.
Natan took on the important task of finishing the developer tutorial. Previously, the tutorial introduced concepts such as setting up a new project, configuring Kotti, adding Poll and Choice content types, and simple views. But it did not have forms to actually vote on the poll. This is now being added.
During the sprint, we also discussed which are the most important topics that the docs don't cover well enough yet. We decided we should add more documentation for users and security, workflows, and a more advanced forms example.
Here's the videos and material for the Writing a Pyramid application tutorial that I gave at last month's EuroPython 2012.
The tutorial is around 3,5 hours long. The accompanying material includes code and documentation for the seven individual steps of the tutorial (ex1_hello through ex7_final).
(Head here if the videos aren't displayed.)
This is the tutorial's complete description of the tutorial from the EuroPython website:
Pyramid is a very general open source Python web framework. As a framework, its primary job is to make it easier for a developer to create an arbitrary web application. The type of application being created isn’t really important; it could be a spreadsheet, a corporate intranet, or a social networking platform. Pyramid is general enough that it can be used in a wide variety of circumstances.
In this tutorial you will build from scratch a simple app in which users each have their individual workspaces, and can invite other users to collaboratively edit content.
While writing the application, you will learn about many aspects of Pyramid. Concretely, you will learn how to:
- Install Pyramid within a virtualenv
- Use Pyramid's scaffolds to quickstart your project
- Work efficiently with templates (using Chameleon)
- Create models and views
- Write your own user authentication
- Make use of Pyramid's Access Control Lists support
- Use Pyramid's Traversal to map URL paths to your objects
- Create forms using the deform form library
- Work with the ZODB, a convenient database to store your Python objects in.
The tutorial will be split into steps with each step accomplishing a certain set of goals. Documented code for all the individual steps, including the final application, will be made available to participants.
Prerequisites: If you're on Mac OSX or Windows and you don't have Python 2.6 or Python 2.7 installed, you might want to run through the Pyramid installation instructions prior to the tutorial.
Last week's Kotti sprint in Berlin was full of win. Here's a summary of what we worked on. (Sprinters: If I forgot to mention anything, please let me know and I'll update.)
Andi (witsch), Marco and Nuno worked on adding search to Kotti. Kotti now has a search box at the top right of the site that searches the 'title' and 'description' fields of content in the database. A setting called kotti.search_content allows the search function to be overridden. Which is where kotti_solr hooks in to provide search through Solr. kotti_solr has a buildout that installs Solr, and it's already working, but will currently only search the same 'title' and 'description' fields. (That is, it will need to grow adapters so that we can extract all searchable text from content.)
The basic search has already landed in Kotti's master branch in Git and will be available in the next version. There's still a few issues that need to be worked on here before that can happen though:
- Do permission checks with search results; at the moment search will return all items, whether the user has permission to see them or not. (Maybe this is a good time to consider adding something like CMF's allowedUsersAndRoles index to Kotti's Node.)
- Document the kotti.search_content setting.
We could also use some help in styling the search box and search results better. You can test drive the search on the demo site.
With this, users will be able to insert codes like [gallery] into their pages and have these render to dynamic elements in the public view. Shortcodes may also take arguments like [table-of-contents level=3]. We discussed this idea back in February on the list.
The team decided they would move the core functionality behind what they call snippets into a separate package pyramid_snippets. The idea is that snippets behave like views with the advantage that they can be easily pulled in via AJAX and be used in other places in the site, like in the portlet columns. The integration with Kotti is happening in the snippets branch. Plans are to add a button to TinyMCE that allows users to add snippets instead of having to remember the codes and syntax.
We also want to eventually deprecate Kotti's slots and unify them with snippets so that slot renderers will become views and can be used as snippets and vice versa.
Anreas (disko) added a new Image type and image scaling to Kotti core. He extracted these out of the nice kotti_imagegallery add-on that he had written earlier.
Predefined image scales include span1 (60x120) to span12 (1160x2320). Additional image scales can be configured through the kotti.image_scales variables.
Andreas (disko) and Daniel worked on improving the rich text editing story for Kotti. Based on the work done on images and scaling by Andreas, they created kotti_tinymce, which is an add-on that provides image and file upload, browsing and insertion through TinyMCE.
One problem with kotti_tinymce is that there's no functional tests. We've just verified that things are working by clicking through all the dialogues manually. Considering that Products.TinyMCE is evolving separately and that we want to maintain upstream compatibility, we really want to implement some browser-based functional tests to be able to guarantee a reasonable level of stability. These tests will also help us fix the remaining bugs in kotti_tinymce.
You can try out the rich text editing improvements on the demo site!
Andreas (disko) and Daniel added HTTP caching into the Kotti core. There's now a default caching policy which may be overridden using the kotti.caching_policy_chooser setting. The default policy is to not cache HTML, cache media for four hours, cache static resources for a month and so on.
The http caching code is based on code previously written by Daniel.
This screencast guides you through the process of creating an add-on for the Kotti content management system. In this tutorial we'll write a simple commenting system in 21 minutes in real-time.
You'll be guided through:
- Installing Kotti itself
- Creating your own Kotti add-on (a Python package)
- Configuring your Kotti site to include your add-on
(Click here if you don't see the video.)
Note: This isn't a programming tutorial. If you're looking for a tutorial because you want to learn Pyramid on your own, head over to the Tutorials section in the offical Pyramid docs.
Recently, the University of Coimbra in Portugal rolled out a shiny new collection of web apps for students and staff. Users can now access through a single platform:
- their email account
- a personalized calendar
- a homepage app where they can manage their own online presence
- their profile, as it's stored in the uni's LDAP, which they can update
- a central panel to manage subscriptions to all Mailman mailing lists available to them
- a help desk application that integrates with the Request Tracker ticket-tracking system
- an application to access documents in the KnowledgeTree document management system
The apps are demoed (rather quickly) in this Portuguese language video. Skip to 1:23 to see them in action:
(Click here if you don't see the video.)
Mario José Bernardes, the project coordinator, draws a diagram that visualizes the different components involved under the hood:
And what you can see here is in fact implemented as a WSGI pipeline. The three boxes AP1 to AP3 at the bottom are the WSGI apps. In front of that we have PA which is a repoze.who based middleware that provides user authentication and single sign-on through Shibboleth and LDAP. And at the top there is a Deliverance middleware that provides the look & feel as well as the header and footer for all pages, including the menu to navigate between the apps.
Now what's really remarkable about this project, apart from its brilliant execution, is that it was developed mostly in-house by a small team of developers and admins, most of who hardly knew Python before they started the project.
How did they end up using Python and Pyramid?
The university is a long-time Silva user, using it for their public website for four years now, and they're very happy with it. They knew that they like Python and wanted to use it to solve more problems.
And that's when I got involved. Back in December '09, I was asked to do two Python tutorial sessions with three days each. The trainees were the in-house developers and most of them complete Python newbies. So the first half of the tutorial was an introduction to Python from the ground up and the second half explained WSGI, Paste and Pyramid (which was still repoze.bfg back then).
In parallel to the training sessions, we put our heads together to think about how a Python implementation of their envisioned web apps portal could look like. Back home from Portugal, I went ahead and wrote some of the core utilities and one example app that could be used as a reference point for programmers writing other apps.
And then it happened: After I delivered the first app, things got very silent. I stopped getting calls, no more emails, not even a single postcard! ... until I realized: the team didn't need me anymore. Python and Pyramid were too damn easy! My days as a consultant would soon be counted. :-)
- Don't teach Pyramid, you'll become useless soon
- Instead recommend hard-to-learn frameworks, or better yet, vendor-tied and hard-to-install black boxes
- Find a new job quick before more people find out about Pyramid
Seriously, what more important metric do we have for choosing one framework over another if not that: How long does it take your team to learn it and be productive with it?
Who did it
These guys rocked apps.uc.pt: Mario José Bernardes, Valentim Branquinho, João Santos, Hugo Branquinho, Pedro Pinheiro, Pedro Almeida and myself.
Next Page »