The example is an adaptation of the following example
Note
This was tested with pylons 0.9.7. To use the latest version of pylons update example accordingly.
Install pylons
$ easy_install pylons
Create a pylons application called MyBlog
$ cd /home/user/workspace $ paster create -t pylons MyBlog $ cd MyBlog
The Models and the Data.
For this example we use the AllegroGraph RDF store. See the Install and Configure AllegroGraph RDF Store page The default engine has been left in, just as in the original example, one can take it out if needed.
3.1. Edit the ~/MyBlog/development.ini file and add the following lines
[app-main] ... surf.reader = allegro_franz surf.writer = allegro_franz surf.server = localhost surf.port = 6789 surf.catalog = repositories surf.repository = surf_blog surf.logging = true surf.clear = false myblog.namespace= http://myblog.com/ns# ...3.2. Edit the ~/MyBlog/myblog/config/environment.py file Add the following lines at the top of the file
from surf import * from myblog.model import *and the following at the end of the load_environment() method
rdf_store = Store(reader = config['surf.reader'], writer = config['surf.writer'], server = config['surf.server'], port = config['surf.port'], catalog = config['surf.catalog'], repository= config['surf.repository']) if config['surf.clear'] == 'true': rdf_store.clear() print 'SIZE of STORE : ',rdf_store.size() # the surf session rdf_session = Session(rdf_store, {}) rdf_session.enable_logging = True if config['surf.logging'] == 'true' else False # register the namespace ns.register(myblog=config['myblog.namespace']) init_model(rdf_session)3.3. Edit the ~/MyBlog/myblog/model/__ init __.py file
from surf import * def init_model(session): """Call me before using any of the tables or classes in the model""" global rdf_session rdf_session = session global Blog Blog = rdf_session.get_class(ns.MYBLOG['Blog'])3.4. Optional You can edit ~/MyBlog/myblog/websetup.py to add initial data in the RDF store or just to run maintenance tasks for your pylons application, but this is not needed yet
3.5. Optional You can setup your application by issuing the following command:
$ paster setup-app development.ini
Putting the script together
4.1. Creating the blog controller
$ paster controller blog
4.2. Edit the ~/MyBlog/myblog/controllers/blog.py file
import logging from pylons import request, response, session, tmpl_context as c from pylons.controllers.util import abort, redirect_to from myblog.lib.base import * from myblog import model log = logging.getLogger(__name__) class BlogController(BaseController): def index(self): c.posts = model.Blog.all(limit=5) return render("/blog/index.html")4.3. Create the template
$ mkdir ~/MyBlog/myblog/templates/blog
4.4. Edit the template ~/MyBlog/myblog/templates/blog/index.html
<%inherit file="site.html" /> <%def name="title()">MyBlog Home</%def> <p>${len(c.posts)} new blog posts!</p> % for post in c.posts: <p class="content" style="border-style:solid;border-width:1px"> <span class="h3"> ${post.dc_title} </span> <span class="h4">Posted on: ${post.dc_created} by ${post.sioc_has_creator}</span> <br> ${post.sioc_content} </p> % endfor <hr/> <a href="/toolkit/index">Admin</a>For this example the following properties were chosen to describe a blog post in this system, the sioc:content describes the content of the post, sioc:has_author describes the author, the dc:created describes the creation date and the dc:title describes the title of the post.
4.5. Edit the ~/MyBlog/myblog/templates/blog/site.html file
<%def name="title()"></%def> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>MyBlog: ${self.title()}</title> </head> <body> <h1>${self.title()}</h1> <!-- *** BEGIN page content *** --> ${self.body()} <!-- *** END page content *** --> </body> </html>4.6. Optional Add the transaction logger to the blog system. Edit the ~/MyBlog/myblog/config/middleware.py file
at the begining
from paste.translogger import TransLoggerin the make_app() method add the following
# CUSTOM MIDDLEWARE HERE format = ('%(REMOTE_ADDR)s - %(REMOTE_USER)s [%(time)s] ' '"%(REQUEST_METHOD)s %(REQUEST_URI)s %(HTTP_VERSION)s" ' '%(status)s %(bytes)s') app = TransLogger(app, format=format, logger_name="access")4.7. Test the application:
$ paster serve --reload development.ini Starting subprocess with file monitor 01:55:52,596 INFO [rdflib] version: 2.4.2 surf.plugin allegro_franz reader : franz libraries installed surf.plugin allegro_franz writer : franz libraries installed 01:55:52,682 INFO [Store] initializing the store 01:55:52,682 INFO [Store] registered readers : ['sparql_protocol', 'allegro_franz', 'sesame2'] 01:55:52,683 INFO [Store] registered writer : ['allegro_franz', 'sesame2'] 01:55:52,711 INFO [Store] store initialized Starting server in PID 14993. serving on http://127.0.0.1:5000Test the application on: http://localhost:5000/blog/index, the following should be displayed:
MyBlog Home 0 new blog posts!4.8. The home pace. Delete the ~/MyBlog/myblog/public/index.html file. Edit the ~/MyBlog/myblog/config/routing.py file
After the # CUSTOM ROUTES HERE add this line
map.connect('/', controller='blog', action='index')
Adding a toolkit. The admin frontend
5.1. Add the toolkit controller
$ paster controller toolkit
5.2. Create the toolkit templates
$ mkdir ~/MyBlog/myblog/templates/toolkit
edit ~/MyBlog/myblog/templates/toolkit/index.html
<%inherit file="/blog/site.html" /> <%def name="title()">Admin Control Panel</%def> This is home of the toolkit. <br> For now you can only <a href="${h.url_for(controller="toolkit", action="blog_add")}">add</a> blog posts. <p> Later on you'll be able to delete and edit also.edit ~/MyBlog/myblog/templates/toolkit/add.html
<%inherit file="/blog/site.html" /> <%def name="title()">Add Blog Post</%def> <span class="h3"> Post a Comment </span> ${h.form('/toolkit/blog_add_process')} <label>Subject: ${h.text('title')}</label><br> <label>Author: ${h.text('author')}</label><br> <label>Post Content: ${h.textarea('content')}</label><br> ${h.submit('Submit','Post New Page')} ${h.end_form()}5.3. Change the controller so that it handles the new actions. Edit ~/MyBlog/myblog/controllers/toolkit.py
import datetime import logging from pylons import request, response, session, tmpl_context as c from pylons.controllers.util import abort, redirect_to from myblog.lib.base import * from myblog import model from surf import * log = logging.getLogger(__name__) class ToolkitController(BaseController): def index(self): return render('/toolkit/index.html') def blog_add(self): return render('/toolkit/add.html') def blog_add_process(self): # Create a new Blog object and populate it. # if you do not specify a subject, one will automatically be generated for you # in the surf namespace newpost = model.Blog() newpost.dc_created = datetime.datetime.now() newpost.sioc_content = request.params['content'] newpost.sioc_has_creator = request.params['author'] newpost.dc_title = request.params['title'] # commit the changes - the session tracks Resources automatically model.rdf_session.commit() # Redirect to the blog home page. redirect_to("/")5.4. Edit the ~/MyBlog/myblog/lib/helpers.py file, add the line in the import section
from routes import url_for from webhelpers.html.tags import *edit the ~/MyBlog/myblog/lib/base.py file, add the line in the import section
import helpers as h
Thant’s it :), Try it out.Test the toolkit interface on: