百度空间 | 百度首页 
 
查看文章
 
Build a blog system with Turbogears in 2 hours - The blog viewing page
2008-10-24 19:54

In the previous posts I've explained how to set up the development environment and how to create a blog editting page as well as save the post. Now it's time to view the blog we have just created. So we need a page where we can see all the blogs.

Let's make this page the default page of our site. To do this, we create a function called 'index':

@expose(template="blog.templates.index")
    def index(self,cid=None,**kw):
        if cid: #category id is provided, return all posts belonging to this category
            category = Category.get(int(cid))
            blogs = list(Blog.selectBy(category=category).orderBy(DESC('time')))
        else:   #all posts
            category = None
            blogs = list(Blog.select().orderBy(DESC('time')))
        return dict(blogs=blogs,category=category,categories=list(Category.select()))

I don't think I need to explain anything here because it's very similar to the functions we have already created in previous tutorials. And also, the index.kid template file is similar too:

<body>
<h1 py:if="category">Posts under ${category.name}</h1>
<h1 py:if="not category">All posts</h1>
<div id="blogs">
    <div py:for="b in blogs" class="blog" id="b${b.id}">
        <div class="subject"><a href="/viewpost?bid=${b.id}">${b.subject}</a></div>
        <div class="author">${b.author}</div>
        <div class="time">${b.time}</div>
        <div class="content">${b.content}</div>
        <div class="etc">
        Category: <a href="/?cid=${b.category.id}">${b.category.name}</a> |
        <a href="/viewpost?bid=${b.id}#comments">Comments(${len(b.comments)})</a> |
        Views(${b.views}) |
        <a href="editblog?bid=${b.id}">Edit</a> |
        <a href="#" onclick="deleteblog(${b.id});return false;">Delete</a>
        </div>
    </div>
</div>
</body>

As you can see, to get the category a post belongs to, all we need to write is blog.category. This is much easier than writing sql expressions.

After we've got these modifications done, we should be able to see a page similar to the following one:

I tuned the css a little bit so that it will not look too ugly.

The tricky part is the Delete link. This time I'll use AJAX to do the deleting job.

<a href="#" onclick="deleteblog(${b.id});return false;">Delete</a>

On clicking this link, a javascript function deleteblog is called:

<script type="text/javascript">
//<![CDATA[
function deleteblog(bid){
    if (confirm('All the comments will be deleted too. This operation cannot be undone. Are you sure you want to delete this blog? ')){
        new Json.Remote('deleteblog',{onComplete: function(result){
                if (result['deleted']==0){
                    blogid = 'b'+bid
                    $('blogs').removeChild($(blogid));   //remove the blog from this page
                    return;
                }
                else{
                    alert('Failed to delete this blog, try again later.');
                    return;
                }
            }}).send({'bid':bid});
    }
}
//]]>
</script>

this script tag should be added into <head></head>. I'm using mootools instead of Turbogears' official javascript lib MochiKit to do the AJAX call here(to me, mootools is a way better js lib than MochiKit). To include mootools, first download mootools.js from their website and copy it to /static/javascript, and then add <script type="text/javascript" src="/static/javascript/mootools.js"></script> into the <head> tag.

This function makes an AJAX call to http://localhost:8080/deleteblog, and send the id of the post('bid') as the parameter. The response is returned in JSON format.

server side function:

@expose(format="json")
    def deleteblog(self,bid=None,**kw):
        if not bid: return dict(deleted=1) #bid not provided, delete failed
        else:
            blog = Blog.get(int(bid))   #get the blog
            for c in blog.comments: c.destroySelf()     #delete all the comments
            blog.destroySelf() #delete the post itself
            return dict(deleted=0) #deleted, 0 indicates success

As you can see, to get all the comments of a blog, you just have to write blog.comments; similarly, category.blogs will get you all the blogs belonging to this category.

the response is passed to the parameter 'result' of function which will be called when the AJAX call is completed. If result['deleted'] is 0, which means we have successfully deleted this post, we remove the post from this page. Pretty simple, isn't it?

Now you should be able to delete a post without refreshing the page.

Are we forgetting anything? Yes, the viewpost page and the comment part. I think by far you have learned enough to create a page all by yourself. I have put all we've got here so far in an archive, which can be downloaded here.

If you have any questions, please drop me a comment. My name is Stone and I'm the web developer of PapayaMobile.com.


类别:Notes | 添加到搜藏 | 浏览() | 评论 (2)
 
网友评论:
1
2008-11-13 22:52
太学术了!!!
 
2
2008-11-30 17:52
什么时候可以平民化一些?这话题深了~~~~~~~
 
本篇日志被作者设置为禁止发表新评论

     

©2009 Baidu