Using IronPython in Umbraco – pyForum part 3

This is the third post in this series and in this we’ll quickly finish up stuff to a point where we have a actual working forum. Well – in a very primitive form.

You can look at and try a running demo here. Later version avaliable here (at a faster server).

At the bottom of this post you’ll find a complete package with templates, document types, macros and scripts – installable at your own Umbraco 4.52+ installation for you to play with.

A macro for viewing a thread and it’s comments

We have the pyForumStart script for our start page that lists our threads and can show and handle a form for adding new threads. Now we also need one for our threads – with a form for new posts. It’s almost exact the same function as pyFormuStart – so we copy that one and just change the template strings, and some minor details in the code.

Going a bit further we could make one or two helper functions instead of our duplicate code, but I leave that for future improvements.

Here’s the complete pyForumThread script:


#
# Imports
#

from umbraco import library
from umbraco.presentation.nodeFactory import Node

#
# We need  System.Web.HttpContext.Current.
#  System.Web should really be a standard reference for the python engine
#

import clr
clr.AddReference('System.Web')
from System.Web.HttpContext import Current

# Add python path
import  sys
sys.path.append(Current.Server.MapPath('~/python'))

from pyForumHelpers  import *

requestType = Current.Request.RequestType

#
# Html Templates
#

threadTemplate  = """

 <div  class="forumthread">
 <h1>{subject}</h1>
 <p>{text}</p>
 <p>By:  <strong>{userName}</strong> {date}</p>
 </div>
 {forumPosts}
 {forumPostForm}
 <p><a  href='{parentLink}'>Back to forum start</a></p>
 """

forumPostTemplate  = """
 <div  class="forumpost">
 <h2>{subject}</h2>
 <p>{text}</p>
 <p>By:  <strong>{userName}</strong> {date}</p>
 </div>
 """

forumPostShowFormTemplate = "<p><a  href='?new=1'>Add a new post</a></p>"

forumPostFormTemplate ="""

 <h2>Add a new  post</h2>

 <form action="#" method="post" id="forumpost">

 <label  for="forumpost-subject">Subject</label><br/>
 <input  type="text" id="forumpost-subject"  name="forumpost-subject"/><br/>

 <label  for="forumpost-text">Text</label><br/>
 <textarea  cols=80 rows=4 id="forumpost-text"  name="forumpost-text"></textarea><br/>

 <label  for="forumpost-user">User (name)</label><br/>
 <input  type="text" id="forumpost-user" name="forumpost-user"/><br/>

 <input type="submit" id="forumpost-submit"  name="forumpost-submit" value="Submit"/>

 </forum>

"""

forumPostMessageTemplate = "<p>Thank  you for your post!</p>"
forumPostErrorMessageTemplate = "<p>Not valid!</p>"

#
# Helper functions
#

def HandleFormPost(id):
    retval = ""
    requestForm = Current.Request.Form
    subject = requestForm["forumpost-subject"]
    text = requestForm["forumpost-text"]
    user = requestForm["forumpost-user"]

    properties = {}
    properties["richtext"]=text
    properties["username"]=user

    if subject:
        create = DocumentCreate("pyForumPost",id,subject,properties)
        retval = forumPostMessageTemplate
        return retval

#
# Main
#

def ForumThreadView():

    def HandleForumForm():
        if requestType=="GET":
            requestNew  = library.RequestQueryString("new")
            if requestNew:
                return forumPostFormTemplate
            else:
                return forumPostShowFormTemplate

        if requestType=="POST":
            return HandleFormPost(currentPage.Id)

    def ForumPostsHtml():
        retval = ""
        for c in Node(currentPage.Id).Children:
            subject  = c.Name
            text = NodePropertyValue(c,"richtext")
            userName = NodePropertyValue(c,"username")
            date = c.CreateDate
            retval += forumPostTemplate.format(subject=subject,text=text,userName=userName, date = date)

        return retval

    forumFormHtml  = HandleForumForm()

    subject = currentPage.Name
    text = NodePropertyValue(currentPage,"richtext")
    userName = NodePropertyValue(currentPage,"username")
    date = currentPage.CreateDate
    parentLink = ""
    if currentPage.Parent:
        parentLink = library.NiceUrl(currentPage.Parent.Id)

    return threadTemplate.format(subject=subject,text=text,userName=userName,forumPosts=ForumPostsHtml(),forumPostForm = forumFormHtml, date=date, parentLink= parentLink)

print ForumThreadView()

I’ve added a link to the parent page “parentLink”. And the sharp eyed see a small fix in the child loop:

        for c in Node(currentPage.Id).Children:

In the first version we had:

        for c in currentPage.Children:

The difference is that the currentPage is created when the umbraco renderer activates the script. And the new child post will be created at a later point, so currentPage wont know about it. The call to Node(Id) however will get the current node data at the time of the call. So to get our new post we need to use that one.

The package

As promised : here’s an installable package of pyForum with all functions up to this point.

The next steps

I’ve written the first three posts now and we are at a point where we have something almost usable. Here’s some future progress ideas:

  • Dress up the forum with a style sheet. Something nice can be made just with a few CSS rules. Also the html string templates are very easy to change if necessary.
  • Remove the user name textbox and put the logged in user name there instead. If we build upon a site with existing membership that would be a piece of cake.
  • Add Javascript for form validation. Also a quick fix using some of the many libraries out there. jQuery validator for example. Inserting some Javascript calls is just a matter of entering the Html code in the document templates.
  • Add some Ajax calls for posting and retrieving the results to spice up the forum. Would not be a biggie either.
  • Add email-notifications. Using membership email addresses and .net messaging makes that easy.
  • Make it possible to edit threads and posts.

I will continue with more posts on this subject, and I indend to make pyForum a usable package in due time. However I don’t know when that will be.

I hope you have found theese first three parts informative and that you’ve been a bit inspired to dive further into IronPython with Umbraco.

Comments, suggestions and questions are most welcome.

Happy coding! / Jonas

Advertisements

2 thoughts on “Using IronPython in Umbraco – pyForum part 3

  1. The source files seem to be missing from the provided link. 404 error.
    This is probably the best and only example of even basic form handling with IronPython, very much appreciated!

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s