体系结构和机制

组织结构

Uliweb 认为一个项目是由不同的模块组成,所以采用了类似于Django App的方式来进行 项目的组织,它们都统一放在 apps 目录下。同时 Uliweb 的App可以是任何符合Uliweb 要求的Python包(使用uliweb makeapp appname创建即可),并且可以是独立的Python 模块放在非apps的地方,只要可以导入就可以了。Uliweb 的 app 的组织重点考虑了功能 及开发的独立性、复用性和配置化,每个 app 可以有自已独立的:

  • settings.ini 它是配置文件
  • templates目录用于存放模板
  • static目录用于存放静态文件
  • views文件,用于存放view代码

这种组织方式使得Uliweb的App重用更为方便。

apps的结构为:

apps/
    .gitignore
    __init__.py
    settings.ini
    local_settings.ini
    app1/
        __init__.py
        settings.ini
        templates/
        static/
    app2/
        __init__.py
        settings.ini
        templates/
        static/
    fcgi_handler.fcgi
    wsgi_handler.py

通过运行 uliweb makeproject projectname 就可以创造一个空的项目。同时在 0.1.6 中会自动添加 .gitignorelocal_settings.ini 文件。其中 .gitignore 已经自动添加了 local_settings.ini 文件。因为 local_settings.ini 主要是 解决不同环境的不同配置问题,所以不应该放入版本中。

App管理

一个项目可以由一个App或多个App组成,而且每个App的结构不一定要求完整,因此一个App可以:

  • 只有一个settings.ini 这样可以做一些初始化配置的工作,比如:数据库配置,i18n的 配置等
  • 只有templates,可以提供一些公共的模板
  • 只有static,可以提供一些公共的静态文件
  • 其它的内容

Uliweb在启动时对于apps下的App有两种处理策略:

  1. 认为全部App都是有效的(这种情况比较少见)
  2. 根据 apps/settings.iniapps/local_settings.ini 中的配置项 INSTALLED_APPS 来决 定哪些App是有效的

Uliweb在启动时会根据有效的App来导入它们自已的settings.ini文件,并将其中配置项进行合 并最终形成一个完整的 settings 变量供App来使用。同时在处理生效的App的同时, 会自动查找所有 views 开头的文件和 views 子目录并进行导入,这块工作主要是为 了收集所有定义在views文件中的URL。

这样当Uliweb启动完毕,所有App下的settings.ini和views文件将被导入。因此,你可以 在App下的 __init__.py 文件中做一些初始化的工作。不过对于大部分的配置工作,建 议采用在 settings.ini 中定义,然后再绑定对应的事件主题的方式,其目的是实现配置化。

App依赖

不同的App之间由于功能上的相互关系可能会产生依赖,因此Uliweb允许在定义App时定义所依赖 的其它的App,这样在配置有效App时,可以减少配置的工作量,在启动时,会自动处理依赖的 App。

Settings处理

Uliweb会按以下顺序来处理 settings.ini 文件:

  1. uliweb/core/default_settings.ini 它是最初始的settings信息
  2. 按定义的顺序导入每个App下的 settings.ini 信息
  3. 导入 apps/settings.ini 信息
  4. 导入 apps/local_settings.ini 信息

如果出现同名配置项,则对于不可变数据类型,后定义的项将覆盖前面定义的值。如果是可 变数据类型,则将进行数据合并。

分散开发,集中使用

Uliweb采用分模块开发,集中使用的原则。即开发时,代码和资源分散在不同的App中,但是 在使用时,将把它看成一个整体进行处理。比如查找某个模板,将在所有的App的templates 中进行查找,按照定义时的倒序进行处理。

URL处理

目前Uliweb支持两种URL的定义方式。

一种是将URL定义在每个view模块中,通过expose来定义。

另一种是在settings.ini中的[EXPOSES]中进行定义。这种方式更适合配置化。

URL的格式采用werkzeug的routing模块处理方式。可以定义参数,可以反向生成URL。在 Uliweb中定义了两个方便的函数:

  • expose 用来将URL与view方法进行映射
  • url_for 用来根据view方法反向生成URL

MVT框架

Uliweb 也采用 MVT 的框架。

Model

目前 Model 是基于 SqlAlchemy 封装的 ORM 。

View

则采函数或类的方式。当 Uliweb 在调用 view 函数时,会自动向函数注入一些对象, 这一点有些象 web2py 。不过 web2py 是基于 exec ,而 Uliweb 是通过向函数注入 变量 (func_globals) 来实现的。这种方式会在某种程序上减少一些导入代码,非常 方便。不过,它只对直接的 view 方法有效,对于 view 函数中又调用的函数无效。 因此你还可以直接通过

from uliweb import request, response

这样的方式来导入一些全局性的对象。

Template

一般你不需要主动来调用, Uliweb 采用自动映射的做法,即当一个 view 函数返回 一个 dict 变量时,会自动查找模板并进行处理。当返回值不是 dict 对象时将不自 动套用模板。如果在 response 中直接给 response.template 指定模板名,可以不 使用缺省的模板。缺省模板文件名是与 view 函数名一样,但扩展名为 .html 。

在使用模板时也有一个环境变量,你可以直接在模板中直接使用预置的对象。同时Uliweb 还提供了对view函数和模板环境的扩展能力。

扩展处理

Uliweb提供了多种扩展的能力:

  • plugin 扩展。这是一种插件处理机制。 Uliweb 已经预设了一些调用点,这些调用点 会在特殊的地方被执行。你可以针对这些调用点编写相应的处理,并且将其放在 settings.py 中,当 Uliweb 在启动时会自动对其进行采集,当程序运行到调用点位置 时,自动调用对应的插件函数。
  • middleware 扩展。它与 Django 的机制完全类似。你可以在配置文件中配置 middleware 类。每个 middleware 可以处理请求和响应对象。
  • views 模块的初始化处理。在 views 模块中,如果你写了一个名为 begin 的函数 ,它将在执行要处理的 view 函数之前被处理,它相当于一个入口。因此你可以在这里 面做一些模块级别的处理,比如检查用户的权限。因此建议你根据功能将 view 函数分 到不同的模块中。