飞仙锅建站日志第2篇-详解django-blog-zinnia

前一篇《飞仙锅建站日志第1篇-初识django-blog-zinnia》讲解了安装blog-zinnia,本文讲解一下zinnia是运行原理以及注意事项。

工作原理

飞仙锅站点工程名叫myzinnia,是一个标准的django工程,zinnia blog源码只是其中的一个应用,她的代码很精简,而且专注博客内容的撰写与展示等功能。

并预留好很多接口,可以很方便的通过反向注入实现功能替换,利用python的对象化特性,实现功能的扩展。

其它主要功能,包括:

  1. 评论功能:使用django-comments(功能太简单了,界面丑,站长后续换成了多级评论)
  2. 标签功能:使用tagging(可用)
  3. 分类功能:使用mptt实现多级分类(实际运营过程中,发现最多三级分类就够了)
  4. 搜索功能:支持全文搜索,后续可以展示讲
  5. pingback: 它和trackback的功能类似,是用来网站互相引用的功能,在国内用的比较少(站长先把它关掉了)

主要扩展功能,通过django-zinnia-xxxx的工程包的形式存在,都可以下载读读源码,下面我先讲两个现在已经在用的两个app:

  1. django-zinnia-ckeditor:方便集成ckeditor富文本框,大大提高码字的效率
  2. django-zinnia-bootstrap:把前端展示展面更换成bootstrap显示样式,这个值得搞个专题好好讲讲

小结一下,zinnia只是django工程的一个app,MTV全部交由django去实现,专注博客的撰写与展示,默认集成了评论、标签、分类、搜索等功能,预留了扩展口和插件,真正做到了短小精悍。

工程配置

要干的第一件事情就是把sqllite换成mysql,在setting.py加入:

import pymysql
pymysql.version_info = (1, 4, 13, "final", 0)
pymysql.install_as_MySQLdb()


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myzinnia',
        'USER': 'root',
        'PASSWORD': 'xxxxxx',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'OPTIONS': {
            'init_command': "SET sql_mode = 'STRICT_TRANS_TABLES'",
            'charset': 'utf8mb4',
        }
    }
}

由于zinnia是歪国人写的,他们干啥事都要用email,自带的评论功能当有人回复你发表的博客文章后会发送一封 email 给你的后台管理员账户邮箱(创建后台管理员账户填写的)。不过需要设置好发送邮件的邮箱,参考配置如下,在 settings.py 中:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.163.com' # 如果不是163邮箱请替换为邮箱服务商的smtp服务器地址
EMAIL_PORT = 465
EMAIL_HOST_USER = 'banditjava@163.com'  # add your own accounts for local test
EMAIL_HOST_PASSWORD = 'xxxxxxxx'
EMAIL_USE_SSL = True
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

应用配置 

在zinnia/settings.py里面,配置了一系列的参数,我贴出几个常用的参数,随意感受一下:

#配置博客主表的扩展类
ENTRY_BASE_MODEL = getattr(settings, 'ZINNIA_ENTRY_BASE_MODEL',
                           'zinnia.models_bases.entry.AbstractEntry')

#配置上传media内容的文件目录
UPLOAD_TO = getattr(settings, 'ZINNIA_UPLOAD_TO', 'uploads/zinnia')

#配置博客列表中,每一个博客展示的内容多少,设定为4看起来会比较舒服
PREVIEW_MAX_WORDS = getattr(settings, 'ZINNIA_PREVIEW_MAX_WORDS', 4)

#配置博客列表每一页的内容条数
PAGINATION = getattr(settings, 'ZINNIA_PAGINATION', 10)

Model

zinnia核心model是zinnia.models_bases.entry.AbstractEntry,当然后续站长对这个类又进行了各种扩展,后续再讲哈:

要读懂这段代码,需要了解更多对象化编程,以及model与database映射的知识,以及对Django有一定的了解。

其中CoreEntry存放最基本的blog的字段,并针content字段包装到ContetnEntry中,并实现了相关的property的逻辑。

其它*Entry也是类似的作用,值得注意的abstract=true,意思是告诉django我只是一个虚拟的,不要在数据库中创建表,等多重继承后再去创建实际的数据表。

代码看起来比挤在一起的字段声明还好多了,当时选zinnia为我的博客源码时,直接么站长看湿了,决定用它了。

class AbstractEntry(
        CoreEntry,
        ContentEntry,
        DiscussionsEntry,
        RelatedEntry, 
        LeadEntry,
        ExcerptEntry,
        ImageEntry,
        FeaturedEntry,
        AuthorsEntry,  
        CategoriesEntry, 
        TagsEntry,
        LoginRequiredEntry,
        PasswordRequiredEntry,
        ContentTemplateEntry,
        DetailTemplateEntry,
        ):
    """
    Final abstract entry model class assembling
    all the abstract entry model classes into a single one.

    In this manner we can override some fields without
    reimplemting all the AbstractEntry.
    """

    class Meta(CoreEntry.Meta):
        abstract = True

Manager

默认情况下,Django为model 添加的manager的名字为objects,你可以自己更改。如果声明成babys,就可以使用Entry.babys.all()来访问。

在CoreEntry中,声明了objects以后,就可以直接使用 Entry.objects.all()来调用。具体的Manager的说明不在这里展开了

objects = models.Manager()

一个关键的property是published,是展示已发布的博客列表,在View中会调用

#发布的文章列表
published = EntryPublishedManager()

Views

在zinnia下面最核心的view是entries.py,代码写得简洁得一P,老司机甚是喜欢这种代码风格,不过对新手来讲很不友好,会吓得一激灵。

简单几行代码,需要了解python的类继承,django的Mixin类,对象缓存,回调函数等知识

别看代码简单,其实数据查询,CRUD预处理,预查询等工作,分别由几个父类来完成了。

所以,只用queryset = Entry.published.on_site这一句话写完了整个方法。

class EntryBaseDateDetailView(BaseDateDetailView):
    def as_view(cls, **initkwargs):
        view = super(EntryBaseDateDetailView, cls).as_view(**initkwargs)
        return view

class EntryDateDetail(ArchiveMixin,
                      EntryArchiveTemplateResponseMixin,
                      CallableQuerysetMixin,
                      BaseDateDetailView):
    """
    Mixin combinating:

    - ArchiveMixin configuration centralizing conf for archive views
    - EntryArchiveTemplateResponseMixin to provide a
      custom templates depending on the date
    - BaseDateDetailView to retrieve the entry with date and slug
    - CallableQueryMixin to defer the execution of the *queryset*
      property when imported
    """
    queryset = Entry.published.on_site


class EntryDetail(EntryCacheMixin,
                  EntryPreviewMixin,
                  EntryProtectionMixin, 
                  EntryDateDetail):
    """
    Detailled archive view for an Entry with password
    and login protections and restricted preview.
    """

Templates

显示模板查找也是django中很重要的知识点,在zinnia这种高度灵活的代码框架里,找模块就变得是一件比痛苦的事情。

zinnia为了灵活性,把显示模块都放到了数据库中,也就是说每一条、或者第一类博客,显示的模板是不一样的。

并且,还有类似blog-zinnia-bootstrap等项目,专门针对zinnia定制了一套模板,但又不是覆盖了所有文件,那模板路径就感觉是满天飞一样,忽左忽右的。

先讲一下django模版路径以及查找顺序

  1. 'DIRS':这是一个列表,在这个列表中可以存放所有的模版路径,以后在视图中使用render或者render_to_string渲染模版的时候,会在这个列表的路径中查找模版。
  2. 'APP_DIRS':默认为Ture,这个设置为True后,会在INSTALLED_APPS的安装了的APP下的templates文件夹中寻找模板。
  3. 查找顺序:
    • 先从'DIRS'中查找,如果没有,则会检查当前APP是否安装
    • 如果已安装,则有先在当前APP目录下寻找,未找到或没有安装则再去其他已安装的APP目录下寻找。
    • 如果均没有查找到,则会抛出TemplateDoesNotExist异常。

在zinnia中,这个模板查找,还需要注意以下几点:

  1. 在zinnia模板名字,entry的模板是跟着数据库走的,在entry.content_template detail_template注明的。
  2. 其它model会根据namespace自动在template里去匹配
  3. 如果自定义了或下载了新的template loader,会根据新的loader去查找模板,直接就返回给django
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'OPTIONS': {
            'loaders': [
                #对,说的就是这个东东,如果放在其它Loader前,先会执行它
                'app_namespace.Loader',
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader',
            ],
        }
    }
]

上面代码展示了,如果有新的Loader,先会执行它,如果找到了模板就直接返回了。

如果在coding时,你怎么改模板也不生效,然后重启服务、重启电脑、清缓存、摔鼠标、砸键盘,依然没有用。

所以,我有一句话要与大家分享:

当你享受到成熟源码框架带来的便利时,你同样也会被它反噬,尤其是你不足够了解它的时候。

以上站长切身感受哈,因为你需要有足够的耐心和专业能力去读懂源码。

结语

以上内容,是飞仙锅和zinnia相处了一段时间以后,熟悉了以后写出来的,原创不易,转载请注明出处.

本文地址:http://www.feixianguo.com/blog/detail/216

评论列表

暂无评论,欢迎来抢沙发!

新的评论

清空