CMS,即Content Management System,内容管理系统。我们这里要开发的小型CMS应用,从结构上和blog应用有些类似,但我们会在这里加入一些新的技术,比如说工作流、搜索功能、编辑组件等。
1.创建项目和应用
我们先来创建本实例的项目,在dos命令提示符下转到Scripts文件夹(如“c:python32Scripts”),然后运行如下命令:
$ django-admin startproject cmsproject
然后在dos命令提示符下继续输入如下命令,进入项目文件夹:
cd cmsproject
注意,以后的绝大部分操作都在这里进行,我们把这个文件夹称作项目的根文件夹。
接下来开始创建应用,在dos命令提示符下输入命令:
$ python manage.py startapp cms
命令执行完后,项目根文件夹下会出现一个叫cms的文件夹,应用创建完毕。
2.建立模型
编辑cms/models.py文件,改成下面这样:
cms/models.py:
from markdown import markdown import datetime from django.db import models from django.db.models import permalink from django.contrib.auth.models import User VIEWABLE_STATUS = [3, 4] class ViewableManager(models.Manager): def get_queryset(self): default_queryset = super(ViewableManager, self).get_queryset() return default_queryset.filter(status__in=VIEWABLE_STATUS) class Category(models.Model): """文章分类""" label = models.CharField(blank=True, max_length=50) slug = models.SlugField() class Meta: verbose_name_plural = "categories" def __str__(self): return self.label class Story(models.Model): """内容管理系统中的一篇文章""" STATUS_CHOICES = ( (1, "待编辑"), (2, "待审核"), (3, "发布"), (4, "存档"), ) title = models.CharField(max_length=100) slug = models.SlugField() category = models.ForeignKey(Category) markdown_content = models.TextField() html_content = models.TextField(editable=False) owner = models.ForeignKey(User) status = models.IntegerField(choices=STATUS_CHOICES, default=1) created = models.DateTimeField(default=datetime.datetime.now) modified = models.DateTimeField(default=datetime.datetime.now) class Meta: ordering = ['modified'] verbose_name_plural = "stories" def __str__(self): return self.title @permalink def get_absolute_url(self): return ("cms-story", (), {'slug': self.slug}) def save(self): self.html_content = markdown(self.markdown_content) self.modified = datetime.datetime.now() super(Story, self).save() admin_objects = models.Manager() objects = ViewableManager()
注意一下,文件要储存为UTF-8编码.
我们可以看到,在Story模型中,引用了两个其他的模型(User和Category)。模型的第一块代码定义了一个包含四个阶段的工作流,当然,你可以给自己的流程添加更多的步骤。
顾名思义,待编辑和待审核的文章,是我们不想让访问者看到的。发布和存档的区别在于,后者是过了一定时间,将其改为存档状态,可以限制它出现在某些特定的地方,比如说首页,但内容还是可以让访问者在其它地方看到。
定义完STATUS_CHOICES之后就轮到变量的定义。
- title:我们要在浏览器的标题栏和渲染页面上显示的标题。
- slug:页面在URL里唯一的名字。
- category:文章分类,这是一个指向Category模型的外键。
- markdown_content:Markdown格式的页面正文(下面会专门介绍Markdown)。
- html_content:Html格式的页面文本。我们会在编辑的时候自动渲染它。为了避免混淆,不可以直接编辑这个变量,因此,它不会在Django的管理界面应用的编辑表单上显示出来。
- owner:拥有这个内容的用户,不一定是管理员,有可能是其它用户。
- status:在编辑工作流中的状态;
- created:创建的时间,自动设置为当前时间(利用Python的datetime模块)。
- modified:修改的时间,初始化为当前时间,这个时间戳会显示在文章的内容页上。
在Meta嵌套类里我们还指定了一个verbose_name_plural的属性,它的作用是避免模型在应用中显示“Storys”这样的错误拼写。
此外还有一个生成永久链接用的get_absolute_url方法,这个我们已经在上一个“网络相册”实例中见过它了。
Category这个模型就非常简单,只有两个变量,一个名称,一个别名。值得注意的是,这是非常方便的一种创建适合的关系型模型的途径。
我们的数据库里同时包含了已发布的(状态3和4)和尚未发布的(状态1和2)文章。我们还需要一种便捷的方式只把前者显示到站点的公共页面上,而在管理界面则显示全部。
虽然我们可以在模板里用{% if %}标签来阻止公共页面显示尚未发布的文章,但这个方案最终会变得异常烦琐和不断重复。因为这里涉及的是业务逻辑而不是表现风格,所以应该在模型中实现这种控制。在Django开发时要把握这样一项原则,永远不要把业务逻辑放到模板中,否则时间长了必定一团乱。模板只要做好显示风格上的事情就可以了,显示哪些数据的问题,还是交给模型和视图来操心吧!
我们把这项控制功能通过自定义Manager加到模型里去,所以我们在import语句的下方加入了一行“VIEWABLE_STATUS = [3, 4] ”,然后是ViewableManager类,ViewableManager控制住文章数据,确保只输出状态等于3或4的文章。
接着,我们在Story模型里用admin_objects = models.Manager()定义了一个manager对象,由于它是先定义的,所以它就是我们模型的默认manager,这样就能保证我们在管理界面编辑所有状态的文章。
然后我们用objects = ViewableManager()创建一个自定义的manager实例。我们将在URL配置和视图使用这个名字,因此所有的公共页面都会收到由自定义ViewableManager输出的经过过滤的queryset。
作为模型的最后一个部分,我们重写了函数save来应用一个轻型的票房语言,叫做Markdown.用户在管理界面用它来输入文本,Markdown提供了一种创建Web内容更简单的方式。
你还可以选用其它标记语言。这里我们主要展示的是如何通过重写模型的save方法来“神奇自动”地把Markdown转换成Html,这样就不需要为每个页面请求执行一次转换操作了。
当然,我们还会有更好的选择,比如说用一个所见即所得的编辑器来代替Markdown,这个大家可以自行研究。
要使用Markdown,你得先去下载Markdown模块,下载地址是:https://pypi.python.org/pypi/Markdown/2.5.1,下载完毕,先解压,然后用python setup.py install命令安装即可。不会安装Python模块的童鞋,请自行百度学习相应的方法。
如何来用好Markdown,可以看这个页面里的资料:http://daringfireball.net/projects/markdown/syntax
3.激活模型
首先修改cmsproject/settings.py这个文件,找到INSTALLED_APPS这段设置,把它改成下面这个样子:
cmsproject/settings.py:
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'cms', )
编辑settings.py的时候,建议顺便修改一下语言和时区的设置,具体的方法请参考:《实战Django:官方实例Part1》
然后在dos命令提示符下运行如下命令:
$ python manage.py makemigrations cms
继续在dos命令提示符下运行命令:
$ python manage.py migrate
这样,数据库就建好了。
4.创建管理员账号
在dos命令提示符下运行如下命令:
$ python manage.py createsuperuser
然后依次输入admin,你的邮箱,输入两次密码,完成创建管理员的操作。
5.在管理界面注册应用
编辑cms/admin.py 文件,让它变成下面这个样子:
cms/admin.py:
from django.contrib import admin from cms.models import Category, Story class StoryAdmin(admin.ModelAdmin): list_display = ('title', 'owner', 'status', 'created', 'modified') search_fields = ('title', 'content') list_filter = ('status', 'owner', 'created', 'modified') prepopulated_fields = {'slug': ('title',)} class CategoryAdmin(admin.ModelAdmin): prepopulated_fields = {'slug': ('label',)} admin.site.register(Category, CategoryAdmin) admin.site.register(Story, StoryAdmin)
6.启动服务器
在dos命令提示符下运行如下命令:
$ python manage.py runserver
还记得如何判断服务器是否成功运行吗?这里就不多讲了。
我们先访问一下管理界面,打开浏览器,在地址栏内输入:
http://127.0.0.1:8000/admin/
然后输入你刚才创建的管理员账号和密码,登录管理界面,你会看到下面这样的画面:
【未完待续】