发布一个Django的论坛系统LBForum(开源、带演示)
二 26, 2010 vicalloy的庄家, 编程
简介
LBForum 用django开发的论坛系统,演示地址为:http://vik.haoluobo.com/lbforum/
项目的地址为:http://github.com/vicalloy/LBForum
界面部分抄的 FluxBB(一个开源的PHP论坛 http://fluxbb.org/ )。
虽然Django写的论坛也不少,不过还真没什么好用的。
大多Django论坛都是独立的app,而且不少还缺模板,想我这样有经验的Django用户要跑起来都觉得麻烦,其他普通用户就更别说了。
LBForum主要注重部署的方便性和易用性,功能方面目前还比较简单。
LBForum一开始就是以整站的形式提供,所以以LBForum做为基础项目进行二次开发是很容易的。
同时LBForum的开发尽量遵照Django可复用app原则,因此即使需要将LBForum做为独立的app集成到其他项目也并不会太难。
主要功能
目前功能还比较简单,而且还有些小问题有待修正。
- 论坛分类,分版块
- 发帖,回帖
- BBCode支持
- 置顶贴
- 使用django admin提供论坛管理功能
用开发服务器把LBForum跑起来
- 先把代码down下来。LBForum托管在github上,http://github.com/vicalloy/LBForum 。如果你没有安装git,你可以直接用界面右上方的download
source功能下载代码。 - 运行\scripts\create_lbforum_env.py初始化lbforum的python虚拟环境。该脚本会自动创建一个python的虚拟环境并使用easy_install安装对应的依赖包,同时将一些依赖包解压到对应的目录中。
注:django使用的是svn版本,所以机器上必须要安装有SVN,不然脚本会运行失败。如果因为由于svn的问题导致脚本运行失败,可以运行lbforum_env.bat进入lbforum环境,手动安装django的svn版本。 - 环境初始化好后,运行lbforum_env.bat进入lbforum环境
- 运行%mg% syncdb初始化数据库
- 运行%mg% runserver启动django开发服务器
- 进入admin,创建论坛分类和版块
- 进入版块发帖
LBForum的目录结构说明
|+lbforum_env/#lbforum运行的python虚拟环境,运行create_lbforum_env.py后自动创建
|+requirements/#lbforum用的第三方库和app,运行的时候会将该目录加到python路径
|~scripts/#工程相关脚本
| |-create_lbforum_env.py#初始化python虚拟环境,并自动安装easy_install/django依赖库
| |-helper.py#提供其他脚本所需的辅助函数
| `-lbforum_env.bat*#启动lbforum运行的虚拟环境及,并为lbforum的manage.py提供快捷方式%mg%,比如初始化数据库%mg%
syncdb
|~sites/#站点配置/模板/静态文件
| `~default/#默认站点
| |+static/#静态资源文件,如css等
| |+templates/#Django模板目录
| |+templates_plus/#Django模板目录,用户将自己重写过的目标放到该目录
| `-……
|~src/#django的app目录
| |+account/#account相关app。具体站点通常会对用户中心进行定制,所以该app在实际应用中很可能需要针对实际情况进行修改。
| |+djangohelper/#一些django的辅助函数等,
| |+lbforum/#lbforum的主app,论坛功能都在改app中
| |+lbregistration/#registration app的lbforum扩展,主要去掉邮件地址认证功能
| |+onlineuser/#显示在线用户的app(可复用的django app,可脱离lbforum单独使用)
| `+simpleavatar/#头像功能的app(可复用的django app,可脱离lbforum单独使用,依赖djangohelper)
|+tools/#工程用到的辅助工具,目前只有一个virtualenv的脚本
注:
- 由于计划在以后做i18n,所以目前只提供英文界面
- django的错误提示是显示在字段后面,fluxbb的错误全部都显示在表单前面。由于模板没有调好,所以目前按照fluxbb的方式显示错误,所以错误显示有些不太正常。
- bbcode的输入框本想做成自适应大小的,不过也调得有些问题,所以现在输入框的大小固定。
- 文档… ,感觉好难写-_-,目前文档不全(项目中没有带任何的文档),日后补上。
- 应用程序的目录结构主要查看pinax
- simpleavatar模块部分代码来自django-avatar
- 依赖包除用easy_install在线安装的外,尽量使用zip包的方式附带在项目中,减少安装依赖包的困难。
- 远程部署脚本计划使用fabric,但fabric本身安装比较麻烦,所暂未处理。
- 项目最早放在googlecode,不过感觉github的功能更强些,所以移了过去。
django的论坛app
十二 20, 2009 编程
在django的资源页面里有个第三方论坛app的比较页面Django Forum Apps Comparison。一眼望过去,可用的app还不真不少,数下了有15个之多。但真正看下来,似乎很难找到一个让人满意的。
我对论坛app的要求是:
- 得要自带一个还比较漂亮的界面模板。
模板的开发工作在django应用的开发中占了很大的比重,甚至可能比写python代码花的时间还多。可惜的是很多的app应用甚至连个最基础的demo模板都没带。 - 最好支持Richeditor和BBCode。
支持BBCode的app还是有几个的。Richeditor的支持基本上属于模板的范畴,参考条目1,似乎还没看到支持Richeditor的论坛(注:我没每个app都看,不能确定,pybb默认模板带了个Markup的编辑器)。 - 支持附件。
国内的论坛应用大多偏娱乐,用户喜欢在自己的帖子里插入图片等东西。虽然可以再单独提供一个上传附件的组件,让用户上传后再在论坛里引用,但用户体验就要差不少了。
既然找不到满意的app,那就只能自己动手做了。目前计划在pybb(注:pybb的许可协议没看太懂,似乎是类似BSD的)的基础上进行开发。目前的开发计划如下:
- 先给项目换个新名字LBForum
- 换个漂亮些的模板(同时增加richeditor)
考虑过不少模板。- phpbb3 目前最流行的开源论坛程序,css和html写得很不错。但似乎有些复杂了,套用起来有些麻烦。
- phpbb2/javaeye/jforum 这几论坛程序都长得差不多,UI应当都是参照phpbb2(javaeye的老大自己说了javaeye的界面就是仿phpbb3)来做的。其实也不能说这几个论坛的模板有什么不好。更多的是不喜欢里面过多的table。
- discuz5 不是太喜欢discuz7的界面。discuz5(springside常用的那款界面)的界面感觉清爽些,但改了些后发现里面的html和css写的实在不怎么样。
- fluxbb 目前打算用她的模板了。界面给人的感觉不错,html和css写得挺好。界面够简单,要套用模板应当不会太困难。
- 增强附件功能
虽然pybb提供了附件的支持,但功能还是比较弱。 - 增加一个公共的个人信息模块
pybb已提供了一个保存用户个人信息的功能,但通常这些信息会是整个工程所共享的。我觉得这些信息还是单独放到一个专有的app里比较好。这个app可以以代码的方式包括的工程里,需要增加个人信息的时候直接修改model代码。
后记
最后还是选择了完全从头进行开发。pybb里面可以用的东西不多,而且他的开发思路和我还是有些分歧。
url_helper简化Django的url配置
六 9, 2009 vicalloy的庄家, 编程
django的url采用正则表达式进行配置,虽然强大却也广为诟病。反对者们认为django的url配置过于繁琐,且不支持默认的路由功能。
我倒觉得还好,只是如果觉得不爽,为什么不自己小小的hack一下,反正也就几行代码的事。
在这个背景下,我整了这个url_helper,利用url_helper可以简化配置和实现url的默认路由。所谓的url_helper其实就只有url_helper.py一个文件,使用的时候只想要import就可以。
url_helper的具体用法请参考具体的例子:
下面对使用方法做个简单的说明。
url的默认路由
from url_helper import execute, url_ import views urlpatterns += patterns('', url(r'^(?P<urls>.*)', execute, {'views': views}), )
在urls.py里增加如下配置,其中views为需要进行路由的views模块。url的规则为 /action/param1/param2/…/ 。
例如:
#/edit/4/ def edit(request, n="id"): html = """ edit object: %s""" % n return HttpResponse(html)
在没有指定action的时候默认使用的action为index。
提供函数url_简化url配置
仿照ROR的做法,参数用”:”标识。
例如:
url_(r’/space/:username/:tag/’, views.url_), 对应的django url配置为url(r’^space/(?P<username>[^/]+)/(?P<tag>[^/]+)/$’, views.url_),
#url_(r’/space/:username/:tag/’, views.url_), #/space/vicalloy/just/ def url_(request, username, tag): html = """ username: %s <br/> tag: %s""" % (username, tag) return HttpResponse(html)
url_helper的完整代码
就如前面说的,代码非常少。不过实际应用的话,应当还需要做一些扩展。
#!/usr/bin/env python # -*- coding: UTF-8 -*- from django import http from django.conf.urls.defaults import url import re def execute(request, urls, views): """ urls [methodName/]param1/param2/.../ methodName default index """ def get_method(views, methodName): try: return getattr(views, methodName) except Exception, e: return None method = None params = [e for e in urls.split("/") if e] params.reverse() if params: method = get_method(views, params.pop()) if not method: method = get_method(views, 'index') if not method: raise http.Http404('The requested admin page does not exist.') return method(request, *params) def url_(*args,**dic): regex = args[0] if regex[0] == "/": regex = regex[1:] regex = '^' + regex regex = regex + '$' regex = re.sub(":[^/]+", lambda matchobj: "(?P<%s>[^/]+)" % matchobj.group(0)[1:], regex) return url(regex, *args[1:], **dic)
Tags: django
DPress-Django开发的Blog
五 29, 2009 vicalloy的庄家
用Django做Blog实在是太过简单,所以在网上可以轻易的找到大量用django实现的Blog,DPress就是其中一个。
本想用这个项目做Django最佳实践的教程,不过发现自己实在是不擅长这个。此外该项目花费的时间比预期的要多出不少,以至到后期挺没耐心,功能方面也因此大幅缩水。
目前DPress的基础功能已经完成,文档方面我会在晚些时候补上。
有兴趣的朋友可以将代码下回来看看。如果要使用Django自己服务器启动起来非常容易。
- 使用SVN把代码下回来 http://dpress.googlecode.com/svn/trunk/ 。
- 运行 \trunk\scripts\init.bat 完成一些必要的初始化(复制静态文件到相关目录)。
- 运行 \trunk\site\dpress\scripts\syncdb.bat 初始化数据库。
- 运行 \trunk\site\dpress\scripts\runserver.bat 启动服务。
- 访问 http://127.0.0.1:8000/admin/ 在管理后台添加日志。
DPress本着以最少的代价完成最多工作的原则,能不造轮子的地方就不造轮子。
- Blog的编辑功能完全交给admin处理。
- 使用filebrowser对admin扩展,实现对文件的管理。
- 使用django-tinymce,实现html的可视化编辑。
- 文章的Tag功能使用django-tagging实现。
- comments功能使用django.contrib.comments。
- Blog本身也大量“借鉴”了pinax的blog组件。
- Blog支持使用书写格式有Markdown、Textile、普通文本,html(支持可视化编辑)、reStructuredText(当然,你需要安装有相关的库)。
对Blog应用来说,一般都会有较高的个性化要求。换肤基本上成了必备功能。很遗憾,这方面是django的软肋。换肤需要创建新的模板,并需要修改配置文件,指定使用新模板。好的方面是,DPress的模板在我优化过后,还是比较简单,改起来还算方便的。
虽然在开始DPress之前就计划的很好,本以为很容易就可以搞定,但事与愿违开发过程中遇中还是遇到了一些麻烦。
Pinax中的Blog组件使用threadedcomments来增加评论支持。在评论内容填写不完整时,会转到它自定义的页面。我认为这是一个挺不友好的设置,尝试修正无果。切换到django.contrib.comments后问题则更糟,不但评论出错会跳到自定义页面,即使评论成功了不会转到评论页面,而是给出一个评论成功的提示。最后没办法,还是自己将添加评论的代码给写了一遍。
此外在模板方面也折腾掉了大量的时间。模板的本身也是程序中重要的一环,但不少的可重用app都没有带任何模板,而且也缺乏模板方面的范例。在我看来,这也是django的第三方app普遍不太好用的重要原因之一。
下面上张图吧,模板的样式,是偷的朋友BLOG的(他也是偷别人的)。

Django资源大全
四 18, 2009 vicalloy的庄家
在wiki上整理了一个关于django的页面,将一些我认为比较有用的信息都列在了上面。
应当说这个页面的第一期工作已经完成了,以后将继续更新。
Tags: django
django-tagging的使用方法
一 7, 2009 编程
django使用app机制来实现组件的重用,充分的利用已有的app可以极大的简化开发工作。目前django下的app虽然还不够丰富,却也还是有部分不错的。django-tagging就是一个不错的app。
现在tag的应用非常广泛,tag基本上成了各网站的必备项目之一,django-tagging就是一个提供tag功能的app。django-tagging提供的功能非常丰富,使用起来却十分简单。下面我就介绍一些常用的用法,让大家对该app有个基本的了解,更详细的介绍还是老老实实的去看django-tagging的使用说明吧:)。
tagging.fields.TagField
我们先定义一个数据库模型Widget,下面的范例都用Widget来进行说明
class Widget(models.Model): name = models.CharField(max_length=50) tags = TagField()
就如上面的代码,只要在数据库模型中增加tags字段就可以为该对象提供tag支持了。tags被映射为CharField,在为对象添加tag时为,英文逗号分割的字符串如:
Widget(name='hello', tags='test,hi,hello')
这样就为新建立的对象添加了test hi hello三个tag了。
获取某个tag下的所有对象的代码如下:
#取出所有属于TAG hi的对象 tag = get_object_or_404(Tag, name='hi') widgets = TaggedItem.objects.get_by_model(Widget, tag)
如要取出Widget用到的所有tag的代码为:
tags = Widget.tags.all()
Tags: django, django-tagging
完成对老照片的调整,Django版本升级到1.0
十二 23, 2008 vicalloy的庄家, 编程
今天完成了对老照片的调整,将Django的版本升级到了1.0。1.0版本的Django相比以前版本相比最大的变化就是那个newforms了。不过好在我在newforms出来不久就直接切换过去了,这次升级只需要在import的时候将newforms改成forms就可以。
admin也是0.96到1.0变化比较大的。不过老照片本来就不太依赖admin,所以我只修改了admin的url映射部分,保证admin后台可以正常打开。以后如果需要用到admin,再对admin部分进行调整。
由于我需要对用户上传的图片进行编辑,因此没有使用Django默认的上传处理。文件上传的变动给我带来了不少麻烦。以前从request.files里取出的文件是个map,但在新版本中变成了一个对象。这个对象虽然提供了files的相关接口,但却又不全,导致PIL无法正常处理。为此我增加了一个临时文件。先将用户上传的文件保存到临时文件再进行处理。在网上看到有用户遇到了和我同样的问题,不知Django在日后的版本中是否会修正。
至于目录的调整,我将那个碍眼的apps给去掉,把所有的文件放到oldphoto这个包下。
此外对项目的配置文件做了一些调整,将默认的数据库改为sqlite,保证程序可以在不做任何设置的情况下直接用manage.py runserver跑起来。
最后再将项目地址贴一下:
http://code.google.com/p/oldphoto/
将项目从SVN中取下后,依次运行scripts目录里的syncdb.bat、runserver.bat就可以跑起来了。当然,那些有些必备的环境还是需要的,python(>=2.4)+django(>=1.0)+PIL。
后记
本来休整工作还包括部分重构以及i18n等,不过在完成Django的升级后就开始没多少兴趣了。由于代码比较老,里面不少东西在现在看来都有更好的处理方式,如果全部都改工作量有点大,只是改部分打打补丁又没多少意思。或许那天重新写个自己看得顺眼点的新项目。