跳转到主要内容

Django buildout 配方

项目描述

此配方允许您通过 zc.buildout 设置 Django 项目。

使用方法

此配方的重点是抽象化 settings.py 文件,使设置位于构建中而不是代码中(例如,在版本控制方面导致尴尬的处理)。settings.py 文件由模板生成,无论是默认模板、默认模板和一个用户扩展,还是完全新的模板。

该模板使用 Tempita 模板系统。

此配方的最基本用法如下

[buildout]
parts = django

[django]
recipe = djc.recipe
project = my.project

其中 my.project 是一个可导入的包,其中包含一个 urls 模块和一个 templates 目录。

正如您所看到的,这里指定的选项非常少:默认值用于构建 settings.py 文件。

当然,真实示例通常更复杂一些:有关更多详细信息,请参阅 选项默认模板选项示例用法

运行测试

位于包内的 README.txt 同时也作为主要的 doctest。

要运行测试,请检出源代码,然后启动 buildout 并运行构建。

$ python bootstrap.py
$ bin/buildout

然后您可以使用以下命令运行测试:

$ bin/test

详细文档

选项

此食谱的选项不是固定的,因为其中许多只在设置模板文件中专用(参见模板化)。

这里我们展示了对食谱有影响的选项:

项目

这标识了一个可以充当项目包的 Python 模块(以点分隔的表示法)。项目包的最低要求是包含一个 urls.py 文件和一个 templates 目录。除非同时定义了 urlconftemplates 选项,否则这是必需的。

urlconf

标识包含 URL 定义的模块:如果省略,则使用 project 中给出的模块内的 urls.py 文件。

模板

标识模板目录。如果省略,则使用 project 中给出的模块内名为 templates 的目录。

静态目录

标识静态内容(图像、CSS 和 JavaScript)将放入的文件夹。相对路径被视为相对于 buildout 目录的相对路径。如果不存在,则创建该目录,如果已存在则不做任何操作。如果省略,则默认为 static

媒体目录

标识上传文件将放入的文件夹。如果省略,则默认为 media

设置模板

如果指定,将使用指定的模板生成 settings.py 文件;如果没有提供,则使用默认模板。有关更多详细信息,请参阅 模板化

设置模板扩展

如果指定,则将指定的模板附加到 settings template 指定的模板或默认模板。

静态源

如果指定,则定义从其中复制必须放入 static-directory 的静态文件的目录:有关更多详细信息,请参阅 静态源

链接静态源

布尔值,默认为 false。如果设置,则文件将通过符号链接而不是复制。仅在 Unix 上工作。

媒体源

如果指定,则定义从其中复制必须放入 media-directory 的数据文件的目录:有关详细信息,请参阅 static-origin 选项。

基本设置

一个设置模块(只有绝对导入),由当前设置扩展,例如 my.module.settings。如果指定,则 appsmiddlewaretemplate-loaders 的默认值变为空字符串(导致它们根本不会被写入)。默认情况下不设置。

WSGI

默认为 false。如果设置为 true(或 on1),将在 parts/$partname 中创建一个名为 $partname.wsgi.py 的脚本,该脚本可以用作 Apache 或其他支持 WSGI 的 web 服务器中的 WSGI 脚本。

wsgi-logfile

如果设置,日志将被重定向到这里:默认不设置。

wsgi-loglevel

设置日志级别:只有在 wsgi-loglevel 也设置的情况下才会处理。接受的值有:debuginfowarningerrorcritical

coding

结果设置文件的编码。默认为 utf-8

高级选项

支持以下高级选项

extra-paths

一些非标准路径,其中包含额外的 Python 模块。

pth-files

一些 pth 文件,从中加载额外的 Python 模块,这些模块应存在于 buildout 中。

initialization

允许添加额外的 Python 代码到 manage 和 WSGI 脚本中:有关详细信息,请参阅 自定义初始化

environment-vars

允许在 manage.py 运行时通过设置它们来覆盖操作系统环境变量。每行一个环境变量名称和值,用空格分隔。变量值可以是硬编码的,也可以使用 buildout 模板机制,其中您引用 buildout 中设置的其它变量。

示例

environment-vars =
        GOOGLE_APPENGINE_PROJECT_ROOT ${buildout:appengine-base-path}
        TZ Europe/Helsinki

如果您希望扩展现有的环境变量,如 PATH,则可能还想检查 gocept.recipe.env buildout 脚本。有关详细信息及示例,请参阅 自定义初始化

模板

settings.py 文件通过将 buildout 节的选项与模板进行插值生成,无论是默认模板还是由 settings-template 选项提供的模板。

模板必须是有效的 Tempita 模板,它将当前 buildout 节的所有选项作为命名空间传递,如下所示

  1. 在选项名称中,所有连字符(-)都转换为下划线(_

  2. 添加了 namesecret 选项,分别映射到 buildout 节名称和随机生成的密钥 [1]

  3. 命名空间中添加了一系列函数,以简化某些情况的处理,以下将提供更多详细信息。

函数

可以在模板中使用一定数量的函数

absolute_url

接受一个路径,如果它是相对的,则将其与 buildout 位置连接起来以使其成为绝对路径。

listify

接受一段数据,将其拆分为行,修剪这些行并返回获得列表,从中清除空字符串。

rfc822tuplize

这个函数相当专业,接受任何符合 Full Name <email.address@example.com> 格式的字符串,并将其转换为包含全名和电子邮件地址的元组。如果提供的数据不符合特定要求,它将返回包含不变数据的元组。

boolify

该函数返回True,如果传入的数据是任何以下值:Trueon1(不区分大小写)否则返回False

join

相当于字符串的join()方法,其中要连接的数据作为第一个参数,infix作为第二个参数,以及两个可选参数prefix(添加到开头)和suffix(添加到结尾)

dump

repr的别名。

默认模板选项

默认模板接受许多选项。如果省略,则认为它们都是可选的,因为会提供合理的默认值。

database

默认Django数据库的设置,形式为engine=<backend> (user=<user> password=<password>) (host=<host>) (port=<port>) name=<name> (options=(<options>))。括号中的值被视为可选。需要注意的是,选项应包含在括号(()中,以逗号分隔,并采用形式<name>=<value>。一个示例URL可能为:engine=django.db.backends.mysql user=usr password=pwd host=localhost port=3306 name=mydb options=(opt1=val1,opt2=val2)其中usrpwdmydb等应替换为您的配置值。默认为engine=django.db.backends.sqlite3 name=/${buildout:directory}/storage.db

additional-databases

name=parameters的形式列出数据库,每行一个,其中name是Django内部数据库名称,而parameters是数据库设置,其形式与database提供的相同

media-url

静态内容前缀路径。默认为media

admin-media

仅管理员使用的静态内容前缀路径。默认为admin_media

timezone

时区:默认为America/Chicago

language-code

语言代码:默认为en-us

use-l10n

是否使用l10n:默认为true

server-mail

来自site-generate邮件的电子邮件地址。默认为root@localhost

admins

RFC822格式列出的网站管理员列表。默认为John Smith <root@localhost>

managers

管理员列表:与admins相同。默认复制admins的值

middleware

要加载的中介类列表。如果为空字符串,则根本不写入值。

apps

要加载的应用程序列表。如果为空,则不写入任何值。

template-loaders

要使用的模板加载器列表。如果为空,则不写入任何值。

debug

如果为true,则激活调试模式。默认为false

internal-ips

在调试时允许查看完整堆栈跟踪的IP地址。默认为127.0.0.1

site-id

Django站点ID。默认未设置。

template-context-processors

Django模板上下文处理器。默认未设置。

authentication-backends

Django身份验证后端。默认未设置

languages

支持的语言列表以 代码 全称 的形式给出,例如 en-us 英语 (美国)。默认为未设置。

mail-backend

要使用的邮件后端。默认为 django.core.mail.backends.smtp.EmailBackend

mail-filepath

如果使用文件邮件后端,请使用此目录。

smtp-host

发送邮件时使用的 SMTP 服务器。默认为未设置。

smtp-port

SMTP 服务器端口。默认为未设置。

smtp-user

连接到 SMTP 服务器的用户名。默认为未设置。

smtp-password

连接到 SMTP 服务器的密码。如果未设置 smtp-user,则此密码无效。默认为未设置。

smtp-tls

连接到 SMTP 服务器时是否使用 TLS(布尔选项)。默认为 false

site-domain

网站域名。默认为未设置。

site-name

网站标题。默认为未设置。

cache-backend

缓存后端。默认为 locmem:///

cache-timeout

缓存超时时间(秒)。默认为 60*5

cache-prefix

缓存前缀(前缀于所有缓存 ID)。默认为 Z

fixture-dirs

搜索 fixtures 的目录。默认未设置。

已弃用选项

这些选项仍在模板中受支持,但它们将等待删除。

database-engine

要使用的数据库引擎。

database-name

要使用的数据库名称。

database-user

连接到数据库服务器时使用的用户名。默认为空字符串。

database-password

连接到数据库服务器时使用的密码。默认为空字符串。

database-host

数据库服务器所在的宿主机。默认为空字符串。

database-port

数据库服务器接受连接的端口。默认为空字符串。

示例用法

首先,我们需要有一个 Django 项目 egg。我们为了测试制作了一个非常简单的 egg,并将其源分发放在 packages 目录下。

当然,您还可以通过其他方式分发和获取项目 egg:例如,在开发过程中,建议使用 mr.developer

清除这些后,我们使用此配方创建了一个最简单的 buildout

>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... """ % cache_dir)

然后运行它

>>> print "start\n", system(buildout)
start
...
Installing django.
Getting distribution for 'dummydjangoprj'.
...
django: Generating settings in ...
django: Making empty static directory ...
django: Creating script at ...
Generated script ...
...
<BLANKLINE>

这为我们生成了一些文件和目录

  1. 位于 bin/django 的 Django manage.py 包装器

  2. 位于 static 的媒体目录(为空,默认选项)

  3. 位于 parts/django/djc_recipe_django/settings.py 的设置文件

所以,正如我们所见,我们在根目录中有一个 static 目录,一个 bin/django 脚本和一个 parts/django 部分

>>> ls(sample_buildout)
-  .installed.cfg
-  .secret.cfg
d  bin
-  buildout.cfg
d  develop-eggs
d  eggs
d  media
d  packages
d  parts
d  src
d  static
>>> ls('bin')
-  buildout
-  django
>>> ls('parts')
d  buildout
d  django

让我们首先看看这个

>>> ls('parts', 'django')
d  djc_recipe_django
>>> ls('parts', 'django', 'djc_recipe_django')
-  __init__.py
-  settings.py

因此,我们可以看到 djc_recipe_django 实际上是一个可导入的 Python 模块。

如果我们检查它

>>> cat('parts', 'django', 'djc_recipe_django', 'settings.py')
# coding=utf-8
SERVER_EMAIL = 'root@localhost'
ADMINS = (
<BLANKLINE>
    ('John Smith', 'root@localhost'),
)
MANAGERS = ADMINS
<BLANKLINE>
<BLANKLINE>
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': '/sample-buildout/storage.db'}}
<BLANKLINE>
TIME_ZONE = 'America/Chicago'
<BLANKLINE>
LANGUAGE_CODE = 'en-us'
<BLANKLINE>
USE_L10N = True
<BLANKLINE>
STATIC_ROOT = '.../static'
<BLANKLINE>
STATIC_URL = '/static/'
<BLANKLINE>
MEDIA_ROOT = '.../media'
<BLANKLINE>
MEDIA_URL = '/media/'
<BLANKLINE>
ADMIN_MEDIA_PREFIX = '/admin_media/'
<BLANKLINE>
SECRET_KEY = '...'
<BLANKLINE>
ROOT_URLCONF = 'dummydjangoprj.urls'
<BLANKLINE>
<BLANKLINE>
TEMPLATE_DIRS = (
    '.../dummydjangoprj/templates',
)
<BLANKLINE>
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = False
<BLANKLINE>
CACHE_BACKEND = 'locmem:///'
CACHE_TIMEOUT = 60*5
CACHE_PREFIX = 'Z'
<BLANKLINE>
DEBUG = False
TEMPLATE_DEBUG = DEBUG

如你所见,这基本上是 Django 的标准 settings.py,由 Django 的 django-admin 创建。它有一个特殊性,即它不在模块中,而是在运行时作为一个名为 _django_settings幽灵 模块加载到适当的 manage 脚本中。

让我们看看 manage 脚本

>>> cat('bin', 'django')
#!...
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import djc.recipe.manage
<BLANKLINE>
if __name__ == '__main__':
    djc.recipe.manage.main('djc_recipe_django.settings')

正如我们所见,manage 模块的 main() 函数被调用,将设置文件作为唯一参数传入。

现在我们可以尝试设置一个示例开发环境,向其中传入 debug = true

>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... debug = true
... """ % cache_dir)
>>> print "start\n", system(buildout)
start
...
Installing django.
django: Making ... a module
django: Generating settings in ...
django: Making empty static directory ...
django: Creating script at ...
Generated script ...
<BLANKLINE>

然后看看生成的设置

>>> cat('parts', 'django', 'djc_recipe_django', 'settings.py')
# coding=utf-8
SERVER_EMAIL = 'root@localhost'
ADMINS = (
<BLANKLINE>
    ('John Smith', 'root@localhost'),
)
MANAGERS = ADMINS
<BLANKLINE>
<BLANKLINE>
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': '/sample-buildout/storage.db'}}
<BLANKLINE>
TIME_ZONE = 'America/Chicago'
<BLANKLINE>
LANGUAGE_CODE = 'en-us'
<BLANKLINE>
USE_L10N = True
<BLANKLINE>
STATIC_ROOT = '.../static'
<BLANKLINE>
STATIC_URL = '/static/'
<BLANKLINE>
MEDIA_ROOT = '.../media'
<BLANKLINE>
MEDIA_URL = '/media/'
<BLANKLINE>
ADMIN_MEDIA_PREFIX = '/admin_media/'
<BLANKLINE>
SECRET_KEY = '...'
<BLANKLINE>
ROOT_URLCONF = 'dummydjangoprj.urls'
<BLANKLINE>
<BLANKLINE>
TEMPLATE_DIRS = (
    '.../dummydjangoprj/templates',
)
<BLANKLINE>
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = False
<BLANKLINE>
CACHE_BACKEND = 'locmem:///'
CACHE_TIMEOUT = 60*5
CACHE_PREFIX = 'Z'
<BLANKLINE>
DEBUG = True
TEMPLATE_DEBUG = DEBUG
<BLANKLINE>
INTERNAL_IPS = (
    '127.0.0.1',
)

模板覆盖

正如在模板化中所述,默认模板可以被覆盖或扩展。

让我们先来扩展它

>>> write('template-extension.py.in',
... """
... # Here we can extend the template, using variables pulled in from the
... # buildout section, with the dashes converted to underscores
... MY_CONFIG_VARIABLE = '{{config_variable_one}}'
... """)
>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... settings-template-extension = template-extension.py.in
... config-variable-one = test
... """ % cache_dir)

启动 buildout,然后查看生成的 settings.py 文件

>>> print system(buildout)
Uninstalling django.
Installing django.
...
Generated script ...
<BLANKLINE>
>>> cat('parts', 'django', 'djc_recipe_django', 'settings.py')
# coding=utf-8
SERVER_EMAIL = 'root@localhost'
ADMINS = (
<BLANKLINE>
    ('John Smith', 'root@localhost'),
)
MANAGERS = ADMINS
<BLANKLINE>
<BLANKLINE>
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': '/sample-buildout/storage.db'}}
<BLANKLINE>
TIME_ZONE = 'America/Chicago'
<BLANKLINE>
LANGUAGE_CODE = 'en-us'
<BLANKLINE>
USE_L10N = True
<BLANKLINE>
STATIC_ROOT = '.../static'
<BLANKLINE>
STATIC_URL = '/static/'
<BLANKLINE>
MEDIA_ROOT = '.../media'
<BLANKLINE>
MEDIA_URL = '/media/'
<BLANKLINE>
ADMIN_MEDIA_PREFIX = '/admin_media/'
<BLANKLINE>
SECRET_KEY = '...'
<BLANKLINE>
ROOT_URLCONF = 'dummydjangoprj.urls'
<BLANKLINE>
<BLANKLINE>
TEMPLATE_DIRS = (
    '.../dummydjangoprj/templates',
)
<BLANKLINE>
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = False
<BLANKLINE>
CACHE_BACKEND = 'locmem:///'
CACHE_TIMEOUT = 60*5
CACHE_PREFIX = 'Z'
<BLANKLINE>
DEBUG = False
TEMPLATE_DEBUG = DEBUG
<BLANKLINE>
<BLANKLINE>
# Extension template template-extension.py.in
<BLANKLINE>
<BLANKLINE>
# Here we can extend the template, using variables pulled in from the
# buildout section, with the dashes converted to underscores
MY_CONFIG_VARIABLE = 'test'

正如你所见,额外的模板简单地追加到了默认模板上,变量 config-variable-one 被替换。

如果我们完全覆盖模板

>>> write('template.py.in',
... """
... # Total override
... FOODS = (
...     {{join(listify(foods), "',\\n    '", "'", "',")}}
... )
... """)
>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... settings-template = template.py.in
... foods =
...     spam
...     spam
...     eggs
...     spam
... """ % cache_dir)

启动 buildout,然后查看生成的 settings.py 文件

>>> print system(buildout)
Uninstalling django.
Installing django.
...
Generated script ...
<BLANKLINE>
>>> cat('parts', 'django', 'djc_recipe_django', 'settings.py')
# Total override
FOODS = (
    'spam',
    'spam',
    'eggs',
    'spam',
)

正如你所见,内置模板被完全丢弃。

静态来源

静态文件通常不是通过 Django 服务的,而是前端 Web 服务器负责通过在文件系统中公开目录来提供它们。

然而,许多静态文件(例如 .js.css)是项目或应用功能的一部分,因此能够将它们与代码一起分发将很有趣。

相关资源可以包含在分发的包中,使用 static-origin 选项可以将它们复制到 static-directory 文件夹中(参见 选项)。

对于媒体文件(例如图像上传)也有类似的特性(选项 media-origin,最终会进入 media-directory)。

static-origin 可以包含静态文件源列表,列表中的每个项可以是 package:directorypackage:directory:destination 的形式;package 是可导入模块的完整点分名称,directory 是包含静态数据的模块内部的路径,destination 是可选的子目录,用于在 static-directory 中复制文件。

那么,让我们从第一个简单的情况开始,只有一个静态数据源。

静态数据源是位于 src 中的开发包 dummydjangoapp1

>>> ls('src', 'dummydjangoapp1', 'dummydjangoapp1', 'static')
-  lib1.js
-  main.css
>>> cat('src', 'dummydjangoapp1', 'dummydjangoapp1', 'static', 'main.css')
body { font-family: "Helvetica" "Arial" sans-serif; }

让我们创建一个 buildout 配置并运行它

>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
... develop = src/dummydjangoapp1
... eggs = dummydjangoapp1
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... static-directory = static
... static-origin = dummydjangoapp1:static
... """ % cache_dir)
>>> rmdir('static')
>>> print system(buildout)
Develop: '.../dummydjangoapp1'
Uninstalling django.
Installing django.
...
django: Making static directory '.../static'
...
Generated script ...
<BLANKLINE>

现在让我们看看 static 里面有什么

>>> ls('static')
-  lib1.js
-  main.css
>>> cat('static', 'main.css')
body { font-family: "Helvetica" "Arial" sans-serif; }

现在让我们尝试使用两个源:第二个是一个名为 dummydjangoapp2 的另一个虚拟应用程序,它像第一个一样位于 src 中。

让我们看看它的 static 中有什么

>>> ls('src', 'dummydjangoapp2', 'dummydjangoapp2', 'static')
-  lib2.js
-  main.css

看起来这个应用程序也定义了 main.css,所以让我们看看内容

>>> cat('src', 'dummydjangoapp2', 'dummydjangoapp2', 'static', 'main.css')
h1 { color: #92B8D8; }

但这会带来问题!当我将其作为第二个源时,两个都定义了 main.css 会发生什么?在这里,最直观的做法可能是覆盖文件,以便底部的源是顶部的 皮肤层

所以如果我们有这个 buildout

>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
... develop =
...     src/dummydjangoapp1
...     src/dummydjangoapp2
... eggs =
...     dummydjangoapp1
...     dummydjangoapp2
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... static-directory = static
... static-origin =
...     dummydjangoapp1:static
...     dummydjangoapp2:static
... """ % cache_dir)

运行后,可以合理预期< span class="docutils literal">main.css 文件的内容是由< span class="docutils literal">dummydjangoapp2 持有的版本提供的,而不是由< span class="docutils literal">dummydjangoapp2 持有的版本。

快速运行并检查确认了这一点

>>> rmdir('static')
>>> print system(buildout)
Develop: '.../dummydjangoapp1'
Develop: '.../dummydjangoapp2'
Uninstalling django.
Installing django.
...
django: Making static directory '.../static'
...
Generated script ...
<BLANKLINE>
>>> ls('static')
-  lib1.js
-  lib2.js
-  main.css
>>> cat('static', 'main.css')
h1 { color: #92B8D8; }

然而,我可能不想让< span class="docutils literal">main.css 覆盖发生,或者任何其他应用程序之间的冲突。这很容易通过以下方式编写的构建来完成

>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
... develop =
...     src/dummydjangoapp1
...     src/dummydjangoapp2
... eggs =
...     dummydjangoapp1
...     dummydjangoapp2
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... static-directory = static
... static-origin =
...     dummydjangoapp1:static:app1
...     dummydjangoapp2:static:app2
... """ % cache_dir)

需要注意的是,现在< span class="docutils literal">static-origin 值有三个元素,最后一个元素是目标目录,它被定义为< span class="docutils literal">static 的子目录:在这种情况下,两个应用程序都位于它们的子目录中,没有发生冲突

>>> rmdir('static')
>>> print system(buildout)
Develop: '.../dummydjangoapp1'
Develop: '.../dummydjangoapp2'
Uninstalling django.
Installing django.
...
django: Making static directory '.../static'
...
Generated script ...
<BLANKLINE>
>>> ls('static')
d  app1
d  app2
>>> ls('static', 'app1')
-  lib1.js
-  main.css
>>> cat('static', 'app1', 'main.css')
body { font-family: "Helvetica" "Arial" sans-serif; }
>>> ls('static', 'app2')
-  lib2.js
-  main.css
>>> cat('static', 'app2', 'main.css')
h1 { color: #92B8D8; }

当然,这种行为不仅在这个情况下有用:应用程序可能实际上需要您将静态文件放置在精确的子目录中,无论其他应用程序是否存在或发生冲突。

WSGI

< span class="docutils literal">wsgi 选项将在< span class="docutils literal">parts 中创建一个小的模块< a href="#footnote-3" id="footnote-reference-3" rel="nofollow">< span class="fn-bracket">[ 3< span class="fn-bracket">] ,这将允许您将您的应用程序连接到上游< span class="docutils literal">wsgi 服务器。

为了有构建,我们必须将配方中的< span class="docutils literal">wsgi 选项设置为< span class="docutils literal">true

>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... wsgi = true
... """ % cache_dir)

并启动构建

>>> print "start\n", system(buildout)
start
...
Installing django.
...
django: Generating settings in ...
...
django: Creating script at .../bin/django
Generated script '.../bin/django'.
django: Creating script at .../parts/django/djc_recipe_django/app.py
Generated script '.../parts/django/djc_recipe_django/app.py'.
<BLANKLINE>

然后,脚本将在< span class="docutils literal">parts/<part_name>/djc_recipe_<part_name> 内创建一个包含< span class="docutils literal">app.py 文件的 Python 模块,该模块可以被 < span class="docutils literal">Apache 或 < span class="docutils literal">uwsgi 加载

>>> ls('parts', 'django', 'djc_recipe_django')
-  __init__.py
-  app.py
-  settings.py
>>> cat('parts', 'django', 'djc_recipe_django', 'app.py')
#!...
<BLANKLINE>
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import djc.recipe.wsgi
<BLANKLINE>
application = djc.recipe.wsgi.main('djc_recipe_django.settings')
<BLANKLINE>
def app_factory(global_config, **local_config):
    """This function wraps our simple WSGI app so it
    can be used with paste.deploy"""
    return application

这将负责将所有必需的路径注入 < span class="docutils literal">sys.path,因此不需要进一步干预。

大多数 < em> WSGI 服务器都会自行有效地处理日志记录,但是如果没有,可以使用单独的日志输出选项:如果设置,将导致所有应用程序日志输出写入指定的文件:< span class="docutils literal">wsgi-logfile

让我们编写构建

>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... wsgi = true
... wsgi-logfile = wsgi.log
... """ % cache_dir)

启动它

>>> print "start\n", system(buildout)
start
...
Installing django.
...
django: Generating settings in ...
...
django: Creating script at .../bin/django
Generated script '.../bin/django'.
django: Creating script at .../parts/django/djc_recipe_django/app.py
Generated script '.../parts/django/djc_recipe_django/app.py'.
<BLANKLINE>

并检查更改

>>> cat('parts', 'django', 'djc_recipe_django', 'app.py')
#!...
<BLANKLINE>
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import djc.recipe.wsgi
<BLANKLINE>
application = djc.recipe.wsgi.main(..., logfile = '.../wsgi.log')
<BLANKLINE>
def app_factory(global_config, **local_config):
    """This function wraps our simple WSGI app so it
    can be used with paste.deploy"""
    return application

如您所见,日志文件参数传递给应用程序:请注意,所有相对路径都是相对于构建根的相对路径。

自定义初始化

有时我们需要在管理脚本和 WSGI 应用程序中添加一些特定的初始化代码,或者在该过程中设置某些环境变量,而无需使用神秘配置。

第一个需求通过 < span class="docutils literal">initialization 选项得到解决:假设我们希望我们的管理和 WSGI 脚本在启动之前检查一个整数是否真的是整数(因此,如果世界已经颠倒,可以安全地终止)。

我们将编写我们的构建

>>> write('buildout.cfg', #doctest:-NORMALIZE_WHITESPACE
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... wsgi = true
... initialization =
...     >>> if not isinstance(1, int):
...     ...     raise TypeError("World has turned upside down")
... """ % cache_dir)

并启动它

>>> print "start\n", system(buildout)
start
...
Installing django.
...
django: Generating settings in ...
...
django: Creating script at .../bin/django
Generated script '.../bin/django'.
django: Creating script at .../parts/django/djc_recipe_django/app.py
Generated script '.../parts/django/djc_recipe_django/app.py'.
<BLANKLINE>

并看到我们的代码在 < span class="docutils literal">bin/django 和 < span class="docutils literal">app.py 中都存在

>>> cat('bin', 'django') #doctest:-NORMALIZE_WHITESPACE
#!...
<BLANKLINE>
import sys
sys.path[0:0] = [
    ...
    ]
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
if not isinstance(1, int):
    raise TypeError("World has turned upside down")
<BLANKLINE>
<BLANKLINE>
import djc.recipe.manage
<BLANKLINE>
if __name__ == '__main__':
    djc.recipe.manage.main('djc_recipe_django.settings')
>>> cat('parts', 'django', 'djc_recipe_django', 'app.py') #doctest:-NORMALIZE_WHITESPACE
#!...
<BLANKLINE>
<BLANKLINE>
import sys
sys.path[0:0] = [
    ...
    ]
<BLANKLINE>
<BLANKLINE>
if not isinstance(1, int):
    raise TypeError("World has turned upside down")
<BLANKLINE>
<BLANKLINE>
import djc.recipe.wsgi
<BLANKLINE>
application = djc.recipe.wsgi.main('djc_recipe_django.settings')
<BLANKLINE>
def app_factory(global_config, **local_config):
    """This function wraps our simple WSGI app so it
    can be used with paste.deploy"""
    return application

需要注意的是,Python 代码的第一行前面加上了 < span class="docutils literal">>>>,而所有后续行都加上了 < span class="docutils literal">...(加一个空格,在两边)。如果想要保留缩进,则必须使用此语法:如果不想使用,则可以省略它们,但必须确保< em>永远不要有结构。

一个更有用的例子是需要设置特定的环境变量,在 django 初始化之前,例如,有人可能想要将 < span class="docutils literal">GOOGLE_APPENGINE_PROJECT_ROOT 设置为 < span class="docutils literal">/my/path。

为了做到这一点,可以使用 < span class="docutils literal">environment-vars 选项:

>>> write('buildout.cfg',
... """
... [buildout]
... parts = django
... offline = false
... download-cache = %s
... newest = false
... index = http://pypi.python.org/simple/
... find-links = packages
...
... [django]
... recipe = djc.recipe
... project = dummydjangoprj
... wsgi = true
... environment-vars =
...     GOOGLE_APPENGINE_PROJECT_ROOT /my/path
... """ % cache_dir)

启动构建

>>> print "start\n", system(buildout)
start
...
Installing django.
...
django: Generating settings in ...
...
django: Creating script at .../bin/django
Generated script '.../bin/django'.
django: Creating script at .../parts/django/djc_recipe_django/app.py
Generated script '.../parts/django/djc_recipe_django/app.py'.
<BLANKLINE>

请确保环境变量初始化代码(通过 os.environ)存在于 bin/djangoapp.py 中。

>>> cat('bin', 'django')
#!...
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
import os
os.environ["GOOGLE_APPENGINE_PROJECT_ROOT"] = r"/my/path"
<BLANKLINE>
<BLANKLINE>
import djc.recipe.manage
<BLANKLINE>
if __name__ == '__main__':
    djc.recipe.manage.main('djc_recipe_django.settings')
>>> cat('parts', 'django', 'djc_recipe_django', 'app.py')
#!...
<BLANKLINE>
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
import os
os.environ["GOOGLE_APPENGINE_PROJECT_ROOT"] = r"/my/path"
<BLANKLINE>
<BLANKLINE>
import djc.recipe.wsgi
<BLANKLINE>
application = djc.recipe.wsgi.main('djc_recipe_django.settings')
<BLANKLINE>
def app_factory(global_config, **local_config):
    """This function wraps our simple WSGI app so it
    can be used with paste.deploy"""
    return application

贡献者

Abstract Open Solutions 赞助的初始开发

变更历史

0.9.7 (2012-07-02)

  • 使 SETTINGS_NAME 可配置 [Simone Deponti]

  • 使多项内容更加符合 Pythonic [Simone Deponti]

  • 弃用了某个版本 [Simone Deponti]

0.9.6 (2012-02-10)

  • 向默认模板添加了 use-l10n 选项 [Simone Deponti]

0.9.5 (2012-01-12)

  • 修复了媒体目录删除错误 [Simone Deponti]

0.9.4 (2012-01-03)

  • 修复了在删除链接树时复制的另一个错误 [Simone Deponti]

0.9.3 (2012-01-02)

  • 修复了静态目录复制错误 [Simone Deponti]

0.9.2 (2011-12-23)

  • 添加了静态和原始的“智能”符号链接 [Simone Deponti]

0.9.1 (2011-12-13)

  • 修复了 reST 的烦恼 [Simone Deponti]

0.9 (2011-12-13)

  • 为初始化代码添加了缩进保留功能 [Simone Deponti]

  • 添加了表示数据库的新默认方式 [Simone Deponti]

  • 添加了引用其他部分的能力 [Simone Deponti]

  • 使 'settings.py' 可导入。 [Simone Deponti]

  • 加快了测试速度。 [Simone Deponti]

0.8.1 (2011-09-22)

  • 修复了 MANIFEST.in [Simone Deponti]

0.8 (2011-09-22)

  • 重构了环境变量支持 [Simone Deponti]

  • 添加了初始化支持 [Simone Deponti]

  • 修复了文档并添加了测试 [Simone Deponti]

0.7.4 (2011-09-15)

  • 更改了存储库位置 [Simone Deponti]

  • 使 DEBUG 明确 [Simone Deponti]

  • 修复了 Windows 上的路径 [Dimitri Roche]

0.7.3 (2011-03-30)

  • 添加了环境变量支持 [Mikko Ohtamaa]

0.7.2 (2010-11-18)

  • 修复了日志记录并添加了 loglevel [Simone Deponti]

0.7.1 (2010-09-23)

  • 修复了多个链接错误 [Simone Deponti]

0.7 (2010-09-23)

  • 添加了静态原始符号链接的能力 [Simone Deponti]

  • 重构了工作集计算以获得更好的性能 [Simone Deponti]

0.6.1 (2010-07-22)

  • 修复了编码错误。 [Simone Deponti]

0.6 (2010-07-20)

  • 添加了新的邮件设置,并重构了默认设置。 [Simone Deponti]

  • 添加了对多个数据库和新式数据库设置的 support [Simone Deponti]

  • 修复了测试和文档中的错误。 [Simone Deponti]

0.5.1 (2010-06-07)

  • 使 wsgi 模块更符合 paster 兼容性

0.5 (2010-06-03)

  • 修复了 MEDIA_URL 的问题 [Simone Deponti]

  • 添加了对 INTERNAL_IPS 的 support [Simone Deponti]

  • 中间件、模板加载器和应用的默认设置已取消 [Simone Deponti]

0.3.2 (2010-06-01)

  • 修复了 WSGI 支持(uwsgi,自定义记录器) [Simone Deponti]

  • 修复了导入错误 [Simone Deponti]

0.3.1 (2010-05-19)

又名“永远不在午夜到早上6点之间发布”

  • 修复了默认模板中 fixture 目录的绝对路径错误 [Simone Deponti]

  • 修复了小的模板扩展错误 [Simone Deponti]

0.3 (2010-05-19)

  • 添加了对多个媒体源的支持 [Simone Deponti]

  • 添加了对 fixture-dirs 的支持 [Simone Deponti]

0.2 (2010-05-17)

  • 第一个公开版本 [Simone Deponti]

0.1 (2010-04-22)

  • 创建了包 [Simone Deponti]

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分发

djc.recipe-0.9.7.zip (63.4 kB 查看哈希值)

上传时间

由以下支持

AWSAWS云计算和安全赞助商DatadogDatadog监控FastlyFastlyCDNGoogleGoogle下载分析MicrosoftMicrosoftPSF赞助商PingdomPingdom监控SentrySentry错误记录StatusPageStatusPage状态页面