Django-Extensions 文档

Django Extensions 是Django框架的扩展功能集合.

包括management命令扩展,数据库字段扩展,admin后台扩展等.

译者注: 文档中包含了部分 git , github , Python env 相关内容, 阅读时遇到相关只是请参考相应文档.

开始

了解Django Eextensions最简单的方式是查看 excllent screencast by Eric Holscher .只要几分钟的时间, Eric就能帮助你了解一半的扩展命令是做什么用的.

安装

使用 pip 安装 django-extensions:

$ pip install django-extensions

还可以从github上下载源码安装:

$ git clone git://github.com/django-extensions/django-extensions.git
$ cd django-extensions
$ python setup.py install

更多安装细节,查看 安装django-extensions.

Python以及Django的兼容性

django-extensions 尽量根据Django版本发布计划支持相应的Django和Python版本 参考Django版本支持说明 [1] .

新版本的 django-extensions 可能在旧版本的Django或Python中也会正常运行,但是我们已经放弃修复与旧版本Django或Python的兼容性bug.

目前支持的Python版本是 2.7, 3.4, 3.5, pypy, pypy3. 支持的Django版本是1.8, 1.9.

目录

安装django-extensions

概要:安装django-extensions

安装

在项目中使用

通过 pip 安装

通过 pip 安装 django-extensions

$ pip install django-extensions

给 django-extensions 贡献代码

django-extensions 代码托管在github:

https://github.com/django-extensions/django-extensions

克隆项目后就可以修改源码

开发版本中的 django command extensions 已经十分稳定, 并能够让你更新到最新的修复代码.

安装开发版本的代码:

$ pip install -e git+https://github.com/django-extensions/django-extensions.git#egg=django-extensions

然后在 src/django-extensions 目录下可以看到源码

并且在你的PYTHONPATH环境变量中已经可以使用django-extensions了. 打开命令行, 检查一下是否可用:

>>> import django_extensions
>>> django_extensions.VERSION
(0, 8)

注意: 这种版本的代码会和正式发布的代码有些不同. 可能包含未知bug和兼容性问题, 但总体来说, 还是值得一试的.

在Django中使用

在Django项目的配置文件中,把 django_extensions 添加到 INSTALLED_APPS 列表中:

INSTALLED_APPS = (
    ...
    'django_extensions',
)

这样就可以在Django的命令行中使用 django-extensions 提供的扩展命令了.

再次运行 ./manage.py help 命令时,就可以看到新的命令.

有些新增的命令依赖其它程序或Python库,例如 [1]

  • ‘export_emails’ 需要 python vobject 模块来创建vcard文件
  • ‘graph_models’ 需要 pygraphviz 库来渲染图片文件.

如果执行的django-extensions命令依赖的程序或库没有安装(或不在当前的环境中),那么这条命令被执行时会抛出异常,并提示缺少的依赖程序或库.

[1]vcard是电子名片的格式

management 命令扩展

概要:management扩展命令列表
  • shell_plus - Django shell的加强版. 自动载入所有app的models,可以方便的使用这些ORM.
  • admin_generator - 提供app名字后, 自动生成Admin类. 生成的代码会输出到标准输出中(STDOUT).
  • clean_pyc - 清除项目编译后产生的全部python的二进制文件
  • create_app - 新建一个app的简便方法,可以通过 --template 参数指定一个app作为创建模板 [1].
  • create_command - 在指定app内创建一个命令扩展目录,方便添加新的扩展命令(或者只能手动创建扩展命令的目录).
  • create_template_tags - 在制定的app内创建模板标签目录
  • create_jobs - 在指定app内创建一个定时任务扩展目录,可以定期执行指定任务.
  • clear_cache - 清除缓存, 在测试和部署过程中十分有用.
  • compile_pyc - 编译项目, 并生成python二进制文件.
  • describe_form - 显示针对一个model的form描述.复制输出的内容到forms.py中可以完整定义一个对应model的form.
  • 删除优化后多余的migrations - 删除冗余的migration文件. migrstion文件在合并优化之后遗留下来的冗余文件是没有用的, 直接删除.
  • dumpscript - 生成一个Python脚本.包含指定app的所有数据对象.与Django的 dumpdata 命令不同的是 dumpscript 导出的是Python对象,而不是纯数据.这种导出数据的方式比直接导出数据或XML文件更容易理解,也更灵活.
  • export_emails - 从用户表中导出联系人信息,支持多种导出格式: Address, Google, Outlook, LinkedIn和 VCard.
  • find_template - 根据给定的模板名称, 查找他的文件路径
  • generate_secret_key - 重新生成一个项目密钥, settigns.py 文件中的 SECRET_KEY 配置.
  • graph_models - 生成一个 GraphViz 文件.将输出内容写入一个文件.以图形化数据模型.传入多个app的名字作为参数,可以在一个文件中显示多个模型的图形化格式 [3].
  • mail_debug - 开启一个邮件服务, 将Django项目发出的邮件从控制台输出, 而不是真的发送出去.
  • notes - 显示python文件和HTML文件中的全部重要备注 比如 TODO, FIXME, BUG, HACK, WARNING, NOTE 和 XXX
  • passwd - 重新设定某个用户的密码,用法: ./manage.py passwd [用户名] .
  • pipchecker - 扫描pip依赖文件 [3] 并找出需要更新的包. 类似于 pip list -o 命令安装依赖包的过程(在虚拟环境中 virtualenv), 只不过它是通过pip依赖文件实现的.
  • print_settings - 与 diffsettings 命令功能类似,但会根据参数显示指定的配置,如果不传参数默认显示的全部配置.
  • print_user_for_session - 通过 session key 来查看当前用户信息,这个方法在查找哪个用户行为导致程序异常非常有帮助. 仅在 SESSION_ENGINE 设置为 'django.contrib.sessions.backends.db' (默认值)的时候才能正常工作
  • drop_test_database - 删除测试数据库. 在自动化测试/部署系统(BuildBot, Jenkins, 等等)中十分有用. 确保测试数据库最终会被清除掉.
  • reset_db - 重置数据库 (目前支持 sqlite3, mysql, postgres),可以用来删除或创建数据库.
  • runjob - 执行一个单独的任务,是 django-extensions 任务系统中的一个功能.
  • runjobs - 按计划定期执行任务. 按 小时,天,周,月执行. 时间计划功能是系统任务的一部分.
  • runjobs - 执行计划任务. 分为按小时执行,按天执行,按周执行,按月执行.是 django-extensions 任务系统中的一部分功能.
  • runprofileserver - 在启动 runserver 测试服务的同时,其用 profile 功能,可以记录服务的详细日志,包含了对于Python方法的详细执行分析.在服务器性能分析时,这是最佳方法了.
  • runscript - 在当前项目的环境下执行脚本.
  • runserver_plus - 在Werkzeug debugger模式下开启服务. 需要安装 Werkzeug. 这是个杀手级应用.
  • set_fake_emails - 根据每个用户的名称, 给所有用户生成一个邮箱, 默认格式为(“%(username)s@example.com”). 生成邮箱的可选参数有: username, first_name, last_name. 仅用于测试
  • set_fake_passwords - 将所有用户的密码设置为一个统一值 (默认密码). 一定要在测试环境下使用.
  • show_template_tags - 显示当前项目可用的模板标签和过滤器.
  • show_urls - 统一显示项目中包含的所有url.
  • sqldiff - 显示app的models与数据库中的表的差别.这个功能非常好用,但还处于实验阶段,虽然不能捕获所有异常,但能很好的检查出不同的内容 [4][4]_.
  • sqlcreate - 根据配置文件的内容,生成创建数据库表的SQL语句.
  • sqldsn - 从Django的配置文件中读取数据库连接参数. 可以提供给其它系统使用.
  • sync_s3 - 将settings.MEDIA_ROOT目录中文件复制到S3中.可以通过参数设置否是使用gzip压缩,文件编码,文件的缓存时间等.
  • syncdata - 把fixture(s)中的数据同步到数据库中, 一条不多, 一条不少.
  • unreferenced_files - 输出所有在 MEDIA_ROOT 路径下, 但是数据库中没有引用的文件名称.
  • update_permissions - 根据参数, 重载指定apps的权限. 如果没有参数, 则重载全部apps的权限.
  • validate_templates - 检查模板中可能存在的语法错误和变异错误.
  • set_default_site - 通过 namedomain 或者 system-fqdn`参数来设置默认站点 `django.contrib.sites 的参数.
[1]Django1.6版本也开始支持通过模板创建app, 参考 https://docs.djangoproject.com/en/1.6/ref/django-admin/#startapp-appname-destination
[3](1, 2) 类似MySQL的relationship map, 将models的关系以描述方式输出,虽然是文本描述,但是使用了GraphViz格式,可以打开成图形

management 下一步计划的功能

概要:这是扩展命令的计划功能, 在未来版本中会得到支持
  • 创建app的 formmanager
  • CSS和JS文件的合并压缩功能

译者注: django-extensions 的新命令增加的功能会依照目前项目的需要.Django版本在演化过程中逐渐增加了很多很有用的命令.CSS和JS文件的合并压缩功能对于某些项目可能并不需呀,因为我们可以在Django项目中包含自己的静态文件解决方案,比如百度的FIS

Admin 后台管理扩展

概要:Admin后台的字段扩展

ForeignKeyAutocompleteAdmin - 该扩展字段在Admin后台中显示为一个搜索输入框. 前端显示的内容由 ForeignKeySearchInput form的weight渲染, 通过jQuery的autocompletion功能实现搜索效果.

用法举例

启用后台管理的自动补全功能,根据示例编辑 admin.py 文件:

from django.contrib import admin
from foo.models import Permission
from django_extensions.admin import ForeignKeyAutocompleteAdmin


class PermissionAdmin(ForeignKeyAutocompleteAdmin):
    # User is your FK attribute in your model
    # first_name and email are attributes to search for in the FK model
    related_search_fields = {
    'user': ('first_name', 'email'),
    }

    fields = ('user', 'avatar', 'is_active')

    ...

admin.site.register(Permission, PermissionAdmin)

如果使用了 django-reversion ,参考下面的例子:

from django.contrib import admin
from foo.models import MyVersionModel
from reversion.admin import VersionAdmin
from django_extensions.admin import ForeignKeyAutocompleteAdmin

class MyVersionModelAdmin(VersionAdmin, ForeignKeyAutocompleteAdmin):
    ...

admin.site.register(MyVersionModel, MyVersionModelAdmin)

如果想要限制搜索功能中的自动匹配, 覆写admin的 get_related_filter 方法. 例如, 添加一条限制给非管理员用户: 仅能向自己创建的文章中添加附件

class AttachmentAdmin(ForeignKeyAutocompleteAdmin):

    ...

    def get_related_filter(self, model, request):
        user = request.user
        if not issubclass(model, Article) or user.is_superuser():
            return super(AttachmentAdmin, self).get_related_filter(
                model, request
            )
        return Q(owner=user)

注意, 某些恶意操作可以绕过这种使用限制(例如一个经过精心构造的伪装请求)

shell_plus

概要:shell命令的扩展命令,运行Django shell的同时自动加载所有app的models,并选择使用Python shell的版本.

交互式的 Python Shells

shell_plus支持不同类型的Python shell.

IPython:

$ ./manage.py shell_plus --ipython

bpython:

$ ./manage.py shell_plus --bpython

ptpython:

$ ./manage.py shell_plus --ptpython

Python:

$ ./manage.py shell_plus --plain

默认shell优先顺序是: ptpython, bpython, ipython, python.

也可以在 settings.py 配置中指定优先选择的shell工具:

# 在shell_plus中使用ipython作为交互工具
SHELL_PLUS = "ipython"

还可以使用 IPython Notebook, 用浏览器作为Python的shell环境

$ ./manage.py shell_plus --notebook

IPython Notebooks交互终端可以在运行时更新, 也就是在Django项目中的代码出现修改后, 通过菜单中的 Kernel > Restart 可以更新运行时的环境.

配置

如果遇到apps中包含的的models名字出现冲突,或不想载入特定apps的models的情况,可以通过配置别名的方法解决:

提示: 下列配置仅在shell_plus中生效,不会影响当前项目运行的环境变量

# 将自动载入的Messages模块重命名为blog_messages

SHELL_PLUS_MODEL_ALIASES = {'blog': {'Messages': 'blog_messages'},}
# 自动载入的 myblog 模型添加前缀
SHELL_PLUS_APP_PREFIXES = {'blog': 'myblog',}
# 不加载sites app和pictures的blog模型

SHELL_PLUS_DONT_LOAD = ['sites', 'blog.pictures']

设置别名和声明不加载的配置可以同时使用.

当引用嵌套模块时, 比如 somepackage.someapp.models.somemodel , 不能添加包(package)和 models 的名字

举例来说:

SHELL_PLUS_DONT_LOAD = ['someapp.somemodel', ]  # This works
SHELL_PLUS_DONT_LOAD = ['somepackage.someapp.models.somemodel', ]  # This does NOT work

也可以通过命令行参数设置不加载的模块:

$ ./manage.py shell_plus --dont-load app1 --dont-load app2.module1

命令行的参数和配置文件中的设置是可以同时使用的,所以一次性的参数完全可以通过命令行运行,省去频繁修改配置文件的麻烦.

shell_plus还能使用 IPython Notebook .将浏览器作为交互的shell:

$ ./manage.py shell_plus --notebook

通过修改2个参数可以自定义 IPython 的行为.

第一个是 NOTEBOOK_ARGUMENTS , 可以追加自定义参数, 需要通过下面方式启动:

$ ipython notebook -h

例如:

NOTEBOOK_ARGUMENTS = [
    '--ip', 'x.x.x.x',
    '--port', 'xx',
]

另一个参数是 IPYTHON_ARGUMENTS ,通过下面方式启动:

$ ipython -h

IPython Notebook 中也会将所有模块和models加载到全局变量中.

IPython NoteBook 中自动加载模块功能是通过参数配置的,默认为启用状态.:

--ext django_extensions.management.notebook_extension

自定义 IPython Notebook 配置需要覆盖Django项目的 IPYTHON_ARGUMENTS 配置:

IPYTHON_ARGUMENTS = [
    '--ext', 'django_extensions.management.notebook_extension',
    '--ext', 'myproject.notebook_extension',
    '--debug',
]

想在 IPython Notebook 中启用自动加载功能,要么包含django-extensions默认的notebook扩展配置,要么把自动加载的代码拷贝到自定义的扩展中.

提示: IPython Notebook 的特性中不能识别 --dont-load 参数.

附加的引入模块

在配置文件中设置 SHELL_PLUS_PRE_IMPORTSSHELL_PLUS_POST_IMPORTS 可以指定附加的引入模块.第一个配置中添加的模块会先于所有模块加载,第二个配置中添加的模块会后于所有模块加载.这两个配置的格式相同,在settings.py文件中添加:

SHELL_PLUS_PRE_IMPORTS = [
    ('module.submodule1', ('class1', 'function2')),
    ('module.submodule2', 'function3'),
    ('module.submodule3', '*'),
    'module.submodule4'
]

上面的配置被转换为Python的引入代码结果,如下所示:

from module.submodule1 import class1, function2
from module.submodule2 import function3
from module.submodule3 import *
import module.submodule4

这些引入的变量在shell执行时就可以使用了.

数据库应用签名

使用PostgreSQL application_name 默认被设置为 django_shell , 这样能够区分 shell_plus 下的查询语句.

SQL 查询

在 shell_plus 中可以输出生成SQL后的的查询语句

$ ./manage.py shell_plus --print-sql

也可以通过配置 SHELL_PLUS_PRINT_SQL 参数, 来实现相同的效果:

# print SQL queries in shell_plus
SHELL_PLUS_PRINT_SQL = True

create_app

概要:创建一个app的简要方法.

--template 参数指定使用一个模板来创建新的app.

--diagram 参数能够从 .dia 文件生成 models.pyadmin.py.

用法举例

例子需要在项目的根目录下执行,该目录下要包含 settings.py 文件 [1]

# 获取命令行的帮助
./manage.py create_app --help
# 从 [APP_NAME].dia 文件中生成 ``models.py`` 和 ``admin.py`` ,这个文件应该放在与 ``settings.py`` 相同的文件目录下
./manage.py create_app -d APP_NAME

从sample.dia文件生成app

./manage.py create_app --diagram=sample.dia webdata

-d 参数或 --diagram 参数通过 dia2django 生成models.py, 详细文档查看 django wiki.

译者注: 新版本Django原生命令 startapp 也提供了通过 --template 指定模板来创建app的功能

[1]这个说法不准确,Django1.4版本后就独立出了配置文件目录,settings.py文件不在项目根目录下.但是这不影响使用,因为项目配置文件是通过manage.py文件指定的.

删除优化后多余的migrations

synopsis:把多个migrations文件优化到一个文件中, 多余的migrations文件就可以移除了

通过替换属性来实现, 移除多个migrations文件优化到一个文件后遗留的多余的migrations文件.

这个自动化过程在 Django migration squashing documentation 中有更多描述. 这个功能会修改源码的文件结构, 小心使用.

用例

安装 django-extensions 后, 可以通过 delete_squashed_migrations 命令移除多余migrations文件.

# Delete leftover migrations from the first squashed migration found in myapp
$ ./manage.py delete_squashed_migrations myapp

# As above but non-interactive
$ ./manage.py --noinput delete_squashed_migrations myapp

# Explicitly specify the squashed migration to clean up
$ ./manage.py delete_squashed_migrations myapp 0001_squashed

dumpscript

概要:生成单独的Python脚本,包含指定app对应的数据库数据对象.可以用来将数据表导入数据库.

dumpscript 命令生成单独的Python脚本,包含了转换成Python对象的数据库数据.这种方法比直接创建数据库或通过XML创建数据库更容易理解,扩展性也更好.

为什么有这个功能

这样做的有几点好处:

  • 数据库变更时会少出现些莫名其妙的错误: 不依赖ID的外键,会忽略掉新增和删除的列
  • 编辑脚本后可以自动生成很多的实例数据

例如,编辑一个脚本,生成一些测试的初始数据到数据库中:

for i in xrange(2000):
    poll = Poll()
    poll.question = "Question #%d" % i
    poll.pub_date = date(2001,01,01) + timedelta(days=i)
    poll.save()

真实情况下数据库可能更大更复杂,通常是通过Admin后台生成一下测试数据,再导出脚本.编辑导出的脚本,得到更多的数据.

特性支持

  • 外键和多对多关系(通过Python变量,而不是ID)
  • 外键或多对多中对自己的引用
  • models子类
  • ContentType 字段类型, 并生成关联关系
  • 递归引用
  • 排除自增字段
  • 父类不会被包含,除非没有子类继承它
  • 可以引用单独的类

如何使用

从指定的app中导出所有models的建表语句:

$ ./manage.py dumpscript appname > scripts/testdata.py

导出指定模型的数据,添加参数 appname.ModelName

$ ./manage.py dumpscript appname.ModelName > scripts/testdata.py

清空指定app对应数据库数据,然后重新加载数据:

$ ./manage.py reset appname
$ ./manage.py runscript testdata

提示: runscript 命令只能执行在 scripts 模块下的脚本,所以要在 scripts 目录下创建 __init__.py 文件.

警告

命名冲突

在命名输出文件时不要与当前环境路径下的文件重名,否则会引起import异常.比如输出到的目标文件与app目录重名时,脚本会尝试加载输出文件而不是app,这是不正确的.

例子:

# 错误用法
$ ./manage.py dumpscript appname > dumps/appname.py

# 正确用法
$ ./manage.py dumpscript appname > dumps/appname_all.py

# 正确用法
$ ./manage.py dumpscript appname.Somemodel > dumps/appname_somemodel.py

runscript

该要:在当前项目环境下执行脚本,这个功能非常有用,它能够允许在不启动Django服务的同时以Django项目的环境变量执行脚本方法.

介绍

runscript 命令允许在django项目的环境下执行任意脚本.就像在 shell 命令中执行脚本一样:

$ python manage.py shell

开始使用

这个例子假设你跟着 Django1.8+ 版本的入门教程, 创建了 polls app,并包含``Question``模型. 我们将创建一个脚本, 从数据库中删除所有``Question``的数据.

首先要在项目根目录下创建一个脚本的目录,名字是 scripts

$ mkdir scripts
$ touch scripts/__init__.py

然后,创建一个想要执行的Python脚本:

$ touch scripts/delete_all_questions.py

这个脚本文件中必须包含 run() 方法, runscript 命令执行时会自动调用该方法.这个脚本中可以引用django项目中的任意模块或数据模型.

例如:

# scripts/delete_all_questions.py

from polls.models import Question

def run():
    # Fetch all questions
    questions = Question.objects.all()
    # Delete questions
    questions.delete()

提示: runscript 命令可以找到任意app下 scripts 目录中的脚本文件.

用法

runscript 命令可以在shell中调用 scripts 目录下的Python脚本.

例如:

$ python manage.py runscript delete_all_questions

提示: runscript 命令会首先检查每个app下的 scripts 目录,如果找到对应名字的脚本就会执行.然后检查 project_root/scripts 目录下是否包含符合名字的脚本,如果找到也会执行.也就是说,我们可以在不同的app中创建相同名字的脚本,并且都会被执行.

参数

--script-args 参数可以接收逗号分隔的值,并将其作为参数传递到方法内,例如

$ python manage.py runscript delete_all_questions --script-args staleonly

例子中 --script-args 参数值作为执行脚本的 run() 方法的参数传入,使用举例

# scripts/delete_all_questions.py
from datetime import timedelta

from django.utils import timezone

from polls.models import Question

def run(*args):
    # Get all questions
    questions = Question.objects.all()
    if 'staleonly' in args:
        # Only get questions more than 100 days old
        questions = questions.filter(pub_date__lt=timezone.now() - timedelta(days=100))
    # Delete questions
    questions.delete()

调试

默认情况下, 代码抛出异常时不会显示错误堆栈. 如果想要跟踪错误堆栈, 需要添加 --traceback 参数. 例如

$ python manage.py runscript delete_all_questions --traceback

export_emails

概要:以不同的格式导出用户的邮件列表

大部分Django站点包含注册用户的信息.有时我们需要将用户邮箱信息导入到其它系统中(生成邮件, Gmail, Google Docs, 修改权限, LinkedLn用户组等等). export_emails 命令为此而设计.导出的用户信息的同时可以对其进行分组.

用法举例

将所有用户信息导出成 '"First Last" <my@addr.com>;' 格式:

$ ./manage.py export_emails > addresses.txt

以LinkedIn pre-approve格式从 Attendees 组中导出用户信息:

$ ./manage.py export_emails -g Attendees -f linkedin pycon08.csv

以GMail(Google Docs)格式创建一个CSV文件:

$ ./manage.py export_emails --format=google google.csv

可选用的格式

address

默认的文本格式,每个实例占一行并保存成如下格式:

"First Last" <user@host.com>;

这可以被用在任意的邮件服务中.

google

CSV格式文件,可以导入到google的应用中.可以被直接用在GMail中,在GMail中添加一组邮件列表,谷歌文档的邀请,谷歌文档权限批量修改,谷歌日历服务,等等.

输出文件仅包含两列.一列是用户名,一列是邮箱地址.这个格式也适合用来做电子表格文件.

outlook

CSV格式文件,可以导入到到Outlook,支持Outlook中的’必填’字段,但只有name和email有值.

linkedin

CSV格式文件,可以被导入到 LinkedIn Groups ,邀请列表中的用户加入该组.

包含3列数据: 邮箱 .这也是最适合电子表格的格式.

vcard

vCard格式,可以被导入到苹果系统的联系人目录中.

Model 字段扩展

概要:数据模型Model的字段扩展

当前数据模型的字段的扩展

  • AutoSlugField - 自动生成一个唯一的slug, 生成方式是以迭代方式给当前字段后面添加一个随机字符, 直到不重复为止.slug生成方式的灵感来自于 SmileyChris 的唯一码生成代码片段.

  • RandomCharField - 自动生成一个指定长度的全局唯一随即字符串. 默认包含数字并区分大小写. 长度为8时, 大约有340万种组合, 长度为12时, 大约有20亿中组合. 参考示例:

    >>> RandomCharField(length=8, unique=True)
    BVm9GEaE
    
    >>> RandomCharField(length=4, include_alpha=False)
    7097
    
    >>> RandomCharField(length=12, include_punctuation=True)
    k[ZS.TR,0LHO
    
    >>> RandomCharField(length=12, lowercase=True, include_digits=False)
    pzolbemetmok
    
  • CreationDateTimeField - DateTimeField类型字段,会自动保存数据第一次被保存到数据库的时间戳.工作方式与添加了 auto_now_add=True 参数相同,而 auto_now_add 参数已经不推荐使用.

  • ModificationDateTimeField - DateTimeField类型字段,当数据出现修改是会自动保存被修改的时间戳.工作方式与添加了 auto_now=True 参数相同. 保存时将update_modified参数设置为False则本次保存不会更新时间戳:

    >>> example = MyTimeStampedModel.objects.get(pk=1)
    
    >>> print example.modified
    datetime.datetime(2016, 3, 18, 10, 3, 39, 740349, tzinfo=<UTC>)
    
    >>> example.save(update_modified=False)
    
    >>> print example.modified
    datetime.datetime(2016, 3, 18, 10, 3, 39, 740349, tzinfo=<UTC>)
    
    >>> example.save()
    
    >>> print example.modified
    datetime.datetime(2016, 4, 8, 14, 25, 43, 123456, tzinfo=<UTC>)
    

也可以直接通过设置实例属性的方式, 禁止自动更新时间戳:

>>> example = MyCustomModel.objects.get(pk=1)

>>> print example.modified
datetime.datetime(2016, 3, 18, 10, 3, 39, 740349, tzinfo=<UTC>)

>>> example.update_modified=False

>>> example.save()

>>> print example.modified
datetime.datetime(2016, 3, 18, 10, 3, 39, 740349, tzinfo=<UTC>)
  • UUIDField - 唯一标识码字段,通过当前系统的Python模块生成的唯一标识码.

    1.4.7 版后已移除: Django 1.8 开始支持原生UUIDField字段. Django-Extensions会支持这个字段直到 Django1.7不再维护.

  • PostgreSQLUUIDField - uid字段, 使用了PostgreSQL的uuid类型.

    1.4.7 版后已移除: Django 1.8 开始支持原生UUIDField字段. Django-Extensions会支持这个字段直到 Django1.7不再维护.

  • EncryptedCharField - 字符串类型字段,会将数据以加密的方式保存和现实,加密方法使用 Keyczar.使用这个扩展字段时需要安装Keyczar,通过Keyczar库生成加密的密钥,还要在django项目的 settings.py 中添加 settings.ENCRYPTED_FIELD_KEYS_DIR 配置,指向密钥的完整目录.

  • EncryptedTextField - 字符串类型字段,与 EncryptedCharField 字段类似,但是继承自 TextField 字段.

  • ShortUUIDField - 字符串类型字段,将生成的uuid转换成较短的字符串(好像是57进制)。生成字符串结果的长度小于22位,通过参数可以生成更短的字符长度,短长度字符虽然不能保证绝对的唯一性,但重复的概率极低

  • JSONField - 基于TextField类型, 并支持JSON的序列化和反序列化. Django 1.9 引入了基于PostgreSQL的 JSONField, 但只能在使用PostgreSQL并且Django版本在1.9以上的用户才能使用.

graph_models

概要:将整个项目或指定app的models结果渲染成图形 [1].

创建一个 GraphViz 格式文件,包含对于指定app的models的描述.可以传入多个app,这样就会把它们渲染到同一个文件中.输出结果通常是一个 .dot 后缀文件.

graph_model 命令可以通过些参数改变生成的图形,比如: 分组模型,包含继承,去除部分模型,改变模型中列的位置等.

新版本的 django-extensions 还可以直接渲染成一张图片,这个功能需要安装 pygraphviz 库.

选择生成图表的库

graph_model 命令可以指定使用哪个库来生成图片,使用参数 --pygraphviz--pydot ,需要安装相应的依赖库.

默认选择 pygraphviz 库生成图表,如果没有指定参数,也没有安装 pygraphviz 库,则会抛出异常.

安装 pygraphviz 库:

$ pip install pygraphviz

安装是可能因为无法编译需要的C扩展而安装失败.那么可能需要尝试其它安装方法,或使用 PyDot.

安装 pydot 库:

$ pip install pyparsing==1.5.7
$ pip install pydot

安装过程很快,注意要安装指定版本的 pyparsing .否则可能会出错:

Couldn't import dot_parser, loading of dot files will not be possible.

默认配置

在项目的配置文件中可以使用 GRAPH_MODELS 配置生成图表时的默认参数:

GRAPH_MODELS = {
  'all_applications': True,
  'group_models': True,
}

配置的参数名与在命令行中的参数名是一样的,只要去掉作为参数的两个建号,并把参数中的减号换成下划线.

模板

Django的模板可以用来生成dot格式文件,通过 pygraphvizpydot 可以把dot文件内容生成图片,这些模板文件是可以扩展和复写的。

使用的模板:

  • django_extensions/graph_models/digraph.dot
  • django_extensions/graph_models/label.dot
  • django_extensions/graph_models/relation.dot

关于如何生成dot文件,可以参考: http://www.graphviz.org/Documentation.php

用例

安装 django-extensions 后,就可以创建 .dot 文件.或通过 graph_models 命令生成图表,看下面的例子:

# 创建一个 .dot 文件
$ ./manage.py graph_models -a > my_project.dot
# 创建一个PNG图片,包含应用的结构,把图片命名为my_project_visualized.png
$ ./manage.py graph_models -a -g -o my_project_visualized.png

# 这个例子中指明了使用哪个Python的图表库
$ ./manage.py graph_models --pygraphviz -a -g -o my_project_visualized.png
$ ./manage.py graph_models --pydot -a -g -o my_project_visualized.png
# 生成一个只包含 'foo' 和 'bar' 应用的 dot 文件
$ ./manage.py graph_models foo bar > my_project.dot
# 生成只包含某些模型的图片
$ ./manage.py graph_models -a -I Foo,Bar -o my_project_subsystem.png
# 生成不包含某些模型的图片
$ ./manage.py graph_models -a -X Foo,Bar -o my_project_sans_foo_bar.png
[1]渲染出的是图形的描述语言,需要用特定软件才能看到图形,如果用文本编辑器打开则会看到描述字符

定时任务

概要:在Django-extensions中使用定时任务.

定时的计划任务

本页介绍的功能正在努力改进中

新建一个与Django的命令执行方式类似的任务 [1].使用 create_jobs 命令在一个app内创建一个 ‘jobs’ 目录,然后可以创建不同的Python脚本执行不同的任务.

django_extensions.jobs 目录中包含了一些简单的例子.

Python的任务脚本继承定时任务类后就会被定义为任务,可以按小时,按天,按周或按月执行.继承的脚本必须实现 execute 方法,该方法在任务触发时会被自动执行.

与任务相关的命令还包括:

  • create_jobs: 创建包含任务的目录
  • runjob: 执行单独的任务
  • runjobs: 执行所有任务

列出所有任务:

runjob[s] -l

未触发时,任务不会自己执行.

任务需要手动执行,或指定时间执行,或在 cron 中配置定期执行

@hourly /path/to/my/project/manage.py runjobs hourly
@daily /path/to/my/project/manage.py runjobs daily
@weekly /path/to/my/project/manage.py runjobs weekly
@monthly /path/to/my/project/manage.py runjobs monthly
[1]意味着可以想Django的shell命令那样引入项目中的app相关类和方法

数据库字段扩展

概要:数据字段的扩展

数据库字段的扩展

  • TimeStampedModel - 抽象类,包含了由自己管理的 createdmodified 字段.
  • TitleDescriptionModel - 虚拟类, 包含了title和description两个字段.
  • TitleSlugDescriptionModel - 虚拟类, 包含了title和description两个字段. 并具有自动管理 slug 字段的功能. slug字段生成字title字段.

命名空间的建议

概要:命名空间的建议

简介

请使用 django_extensions 的命名空间,而不是绝对路径

命名空间的建议

一些简单的建议:

  • django_extensions.commands (20% 的人在正式环境中使用的绝对路径)
  • django_extensions.commands.development (所有在开发中都会用到的功能)
  • django_extensions.commands.extra
  • django_extensions.db
  • django_extensions.templates
  • django_extensions.jobs

数据库部分使用方式都是正确的,因为目前只有一种引用方式:

from django_extensions.db.models import something

runprofileserver

首先,在跟踪分析一门语言和框架前,应该深入了解一下正在使用的语言(框架),这样才能事半功倍.不够扎实的功底会导致在跟踪分析服务时做出错误的假设和判断.有一条经验法则很实用:干净整洁的代码比热情和耐心更实用.

这部分功能正在持续改进中,如果你有好的办法能够跟踪,分析Django框架,请给我们留言

简介

runprofileserver 命令在启动django服务的同时其用了跟踪分析工具,会将服务的分析信息保存到 .prof 后缀文件中.使用 --prof-path 参数指定保存分析文件到指定目录.每一个请求的分析数据都会被保存成一个profile文件.

如果没有指定 --prof-path 参数,分析数据的 .prof 文件会被保存到 /tmp 目录下.建议使用特定目录保存分析文件,这样方便我们随时查看分析数据,也不会弄乱 /tmp 目录,使用windows系统时一定要指定``–prof-path`` 参数,因为windows系统没有 /tmp 目录.

分析文件的名字默认名字是:

{path}.{duration:06d}ms.{time}

也可以通过 --prof-file 参数指定生成的服务分析文件名字.文件名格式规则参考: Format Specification.

例如:

  • “{time}-{path}-{duration}ms” - 用请求的道达时间命名分析文件.
  • “{duration:06d}ms.{path}.{time}” - 用请求的相应时间命名分析文件.

聚合profile

Django提供了一个profile文件聚合的工具 gather_profile_stats.py ,在Django安装目录的 bin 目录下可以找到.

Profiler选择

runprofileserver 支持两种 profilers : hotshotcProfile. 两个都是Python标准库. cProfile 比较新, 而且可能不支持所有系统. 所以默认的 profiler 是*hotshot*.

但是 hotshot 已经不再维护了. <https://docs.python.org/2/library/profile.html#introduction-to-the-profilers>`_ cProfile 通常是一个更好的选择. 通过 --use-cprofile 参数来检测当前系统是否支持 cProfile;

例子:

$ mkdir /tmp/my-profile-data
$ ./manage.py runprofileserver --use-cprofile --prof-path=/tmp/my-profile-data

如果使用默认profiler后, pstats 模块和 GUI 工具都打不开记录, 并且提示 “ValueError: bad marshal data (unknown type code)”. 尝试使用*cProfile*作为profiler来解决问题.

KCacheGrind

新版本的 runprofileserver 命令可以把分析的结果文件保存成 KCacheGrind 格式文件,这样就可以通过 KCacheGrind 的分析工具来查看分析数据.

例子:

$ mkdir /tmp/my-profile-data
$ ./manage.py runprofileserver --kcachegrind --prof-path=/tmp/my-profile-data
Validating models...
0 errors found

Django version X.Y.Z, using settings 'complete_project.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[13/Nov/2008 06:29:38] "GET / HTTP/1.1" 200 41107
[13/Nov/2008 06:29:39] "GET /site_media/base.css?743 HTTP/1.1" 200 17227
[13/Nov/2008 06:29:39] "GET /site_media/logo.png HTTP/1.1" 200 3474
[13/Nov/2008 06:29:39] "GET /site_media/jquery.js HTTP/1.1" 200 31033
[13/Nov/2008 06:29:39] "GET /site_media/heading.png HTTP/1.1" 200 247
[13/Nov/2008 06:29:39] "GET /site_media/base.js HTTP/1.1" 200 751
<ctrl-c>
$ kcachegrind /tmp/my-profile-data/root.12574391.592.prof

runserver_plus

概要:runserver_plus 命令启动测试服务,并用 Werkzeug 作为调试后台,这个命令是对原生命令 runserver 的扩展,提供了更强的错误调试功能.

简介

runserver_plus 命令需要安装 Werkzeug WSGI utilities . Werkzeug 是Python作为web服务的杀手级调试工具,还能进行基于ajax的错误断点调试(允许在出错的地方执行代码). 当然还提供了一个漂亮的错误展示页面.

开始使用

在启动Django的测试服务时,只要用 runserver_plus 命令代替 runserver 命令就可以了:

$ python manage.py runserver_plus

* Running on http://127.0.0.1:8000/
* Restarting with reloader...

Validating models...
0 errors found

Django version X.Y.Z, using settings 'screencasts.settings'
Development server is running at http://127.0.0.1:8000/
Using the Werkzeug debugger (http://werkzeug.pocoo.org/)
Quit the server with CONTROL-C.

runserver_plus 命令接受原来的所有参数.也就是可以随意指定端口和host,跟原生的 runserver 命令一模一样.

深入使用

runserver_plus 启动的服务遇到代码抛出异常时,会得到一个 Werkzeug 的错误显示页面(不是默认的Django错误页面).

werkzeug-traceback

当鼠标划过特定错误行(堆栈)时,就会显示出当前位置的调试扩展功能,注意图片右边出现的2个按钮:

werkzeug-options

这2个选项是:

查看源码

这是点击 显示源码 后的效果:

werkzeug-source

产看错误产生的源码有助于快速定位错误原因.抛出异常的部分被高亮显示,这样更方便查看.

有一个不够人性化的地方是,点击 查看源码 后,页面没有自动滚动到底部(源码显示的地方),这容易让人觉得什么都没有发生,其实是没有看到.

命令行调试

在错误页面上点击命令行调试按钮后,会显示出一个命令行调试工具(网页里面的输入框),是不是屌爆了:

werkzeug-debugger

这样就会出现一个基于ajax的命令行调试工具,输入的命令通过ajax方式发送到后台,再把返回的结果输出,然后就可以任意发挥了.截图中,在调试框里输入了 print environ 命令来查看当前环境中给方法传入了哪些参数.

注意 : 该方法不能被用在任何正式环境中,即使是在正式环境中检测问题时也不行.命令行调试工具允许在服务器端执行Python命令,这是非常危险的.

SSL

runserver_plus 还支持SSL,这样就可以方便的调试 https 请求了.使用SSL时需要提供证书的名字, runserver_plus 会自动生成一个证书:

$ python manage.py runserver_plus --cert cert
Validating models...
0 errors found

Django version X.Y.Z, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Using the Werkzeug debugger (http://werkzeug.pocoo.org/)
Quit the server with CONTROL-C.
 * Running on https://127.0.0.1:8000/
 * Restarting with reloader
Validating models...
0 errors found

Django version X.Y.Z, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Using the Werkzeug debugger (http://werkzeug.pocoo.org/)
Quit the server with CONTROL-C.

执行上面的命令后就可以通过 https://127.0.0.1:8000 在安全模式下访问服务了.在项目目录下会创建2个新的文件,分别是密钥文件和证书文件.重启测试服务时,这2个文件会被保留下来,这样浏览器就不用反复处理证书授权了.如果想使用指定证书文件,可以使用路径参数指向该证书文件:

$ python manage.py runserver_plus --cert /tmp/cert

使用SSL时需要安装 OpenSSL 库. Werkzeug 0.9版本后才允许重用证书文件.通过以下命令安装 OpenSSL 库:

$ pip install pyOpenSSL

配置

设置 RUNSERVERPLUS_SERVER_ADDRESS_PORT 来跳转开发环境中使用的地址和端口

如果可以通过以下命令启动服务:

$ python manage.py runserver_plus 0.0.0.0:8000

那么就可以设置开发时使用的默认地址和端口:

RUNSERVERPLUS_SERVER_ADDRESS_PORT = '0.0.0.0:8000'

添加设置, 使Werkzeug在console中输出log:

LOGGING = {
    ...
    'handlers': {
        ...
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        ...
        'werkzeug': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

CPU及IO的用量

这个问题 gh625 导致 runserver_plus 在系统空闲时会占用很多系统资源. 这是因为 Werkzeug 包含了一个自动重新加载的功能. 通过 stat pollingfile system events 两种方式来实现自动重新加载.

stat polling 这种自动重新加载的方式十分简单粗暴. 导致的问题是系统资源占用率高.

安装 Watchdog 包后, 它会不断尝试使用 file system events 方式, 能使用就自动使用.

更多内容参考 Werkzeug 文档

通过两种方式来设置自动重新加载的参数, Django配置文件:

RUNSERVERPLUS_POLLER_RELOADER_INTERVAL = 5

或者通过命令行参数”

$ python manage.py runserver_plus –reloader-interval 5

调试 (Debugger PIN)

摘要:

下面有关调试的说明来自 Werkzeug_ 的文档

 -- http://werkzeug.pocoo.org/docs/0.11/debug/#debugger-pin

Werkzeug 0.11 开始调试工具受到PIN的保护. 这种方式能模拟生产环境, 真实的用户使用的情景下调试. PIN默认开启认证功能.

调试器启动时, 首先会在命令行里输出PIN, 这个PIN是通过安全方式生成的并针对当前项目的. 由环境变量 WERKZEUG_DEBUG_PIN 生成的PIN, 遇到服务重启的时候很难达到安全模式. This can be set to a number and will become the PIN. This variable can also be set to the value off to disable the PIN check entirely.

如果执行了多次错误的PIN的插入方式, 那么就需要重启当前服务了.

这个功能不是为了鼓励线上调试的. 而是为了避免攻击者利用线上调试功能. 在生产环境中, 永远不要开启调试功能.

sync_s3

概要:将项目的 MEDIA_ROOTSTATIC_ROOT 目录包含的文件同步到S3 [1].

sync_s3 命令会检索配置中的 settings.MEDIA_ROOT 目录和 settings.STATIC_ROOT 目录,然后把所有文件资源上传到S3的相同的目录结构下.

sync_s3 命令可以启用以下功能,通过传入参数启用对应功能,默认全部关闭:

* gzip 压缩CSS和JS文件,并添加 ``Content-Encoding`` 头.
* 设置文件缓存过期时间
* 只上传 media 或 static 目录文件.
* 使用其它的S3同步工具
* 设置public文件的访问控制列表

用法举例

上传到S3的 mybucket

$ ./manage.py sync_s3 mybucket

上传到S3的 mybucket ,并对CSS/JS文件进行gzip压缩和添加缓存过期时间:

$ ./manage.py sync_s3 mybucket --gzip --expires

只上传 media 文件到S3的 mybucket 中

$ ./manage.py sync_s3 mybucket  --media-only  # or --static-only
# Upload only media files to a S3 compatible provider into the bucket 'mybucket' and set private file ACLs
$ ./manage.py sync_s3 mybucket  --media-only  --s3host=cs.example.com --acl=private

依赖的库和配置

sync_s3 命令需要安装 boto 库,改命令在1.4c版本下测试通过:

当然还要添加AWS账户的S3密钥和bucket名称,在项目配置文件 settings.py 文件中增加配置:

# settings.py
AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''
AWS_BUCKET_NAME = 'bucket'

可选配置

可以在 settings.py 文件种设置好全部的 sync_s3 的参数,实现自动上传

# settings.py
AWS_S3_HOST = 'cs.example.com'
AWS_DEFAULT_ACL = 'private'
SYNC_S3_PREFIX = 'some_prefix'
FILTER_LIST = 'dir1, dir2'
AWS_CLOUDFRONT_DISTRIBUTION = 'E27LVI50CSW06W'
SYNC_S3_RENAME_GZIP_EXT = '.gz'
[1]S3是亚马逊提供的云存储服务,也是目前行业中使用最广泛的云存储服务.2013年底亚马逊云服务才宣布正式入华,估计2014年中旬才能用上.

sqldiff

概要:sqldiff 命令会检测指定app与数据库表之间的差别,并输出数据库表的修改语句.

sqldiff 命令不是用来合并数据库差别的工具,虽然能够查看区别,但这个命令的设计初衷只是检查数据库表结构与django数据模型的区别.

支持的数据库

sqldiff 命令当前支持的数据库:

  • PostgreSQL
  • Sqlite3
  • MySQL
  • Oracle

欢迎提供支持其它数据库的 patch ! :-)

退出时的状态码

退出状态码有3种:

  • 0 与输入相同
  • 1 与输入不同
  • 2 异常

用法举例

查看所有app数据模型与数据库之间的区别:

$ ./manage.py sqldiff -a

用文本显示所有app数据模型与数据库之间的区别:

$ ./manage.py sqldiff -a -t

sqlcreate

概要:sqlcreate 命令可以更方便的创建数据库.

简介

不用再手动创建数据库, settings.py 文件中已经包含了需要的信息,所以Do It Yourself.

用法

$ python manage.py sqlcreate [--router=<routername>] | <my_database_shell_command>

sqlcreate 命令会将SQL语句输出用来检查(如果你想检查的话).但最终还是要输入到数据库的shell中来执行.

如果有合适的方法证明当前用户有修改数据库的权限,那就可以把输出结果直接导入到数据库中.但是因为项目的配置方式,这种直接修改数据库的方式是不能接受的.

用法举例

PostgreSQL

$ ./manage.py sqlcreate [--router=<routername>] | psql -U <db_administrator> -W

MySQL

$ ./manage.py sqlcreate [--router=<routername>] | mysql -u <db_administrator> -p

存在的问题

  • CREATE DATABASE 不是SQL标准语句,所以可能不能支持所有数据库 [1].
  • 回滚数据库时没有创建用户名及密码,但会尝试将数据库权限分配一个用户 [2] .
  • 缺少表空间的设置,等等.
[1]sqlite3 数据库创建就不是通过CREATE DATABASE语句,不过绝大多数数据库都没问题.
[2]译者也不确定明白这个问题指的是什么.sorry.

sqldsn

概要:在标准输出中打印数据资源的名称和关系.

支持的数据库

目前仅支持下面的数据库:

  • PostgreSQL (psycopg2 or postgis)
  • Sqlite3
  • MySQL

欢迎贡献代码, 支持更多的数据库! :-)

退出状态码

退出状态码始终是 0

用法举例

# 打印默认数据库资源名称
$ ./manage.py sqldsn
# 打印所有数据库资源名称
$ ./manage.py sqldsn --all
# 打印 'slave' 数据库的资源名称
$ ./manage.py sqldsn --router=slave
# 打印默认数据库所有可用资源
$ ./manage.py sqldsn --style=all
# 使用 quite(安静) 模式, 通过默认数据库生成 .pgpass 文件
$ ./manage.py sqldsn -q --style=pgpass > .pgpass

validate_templates

概要:检查模板的语法错误或编译错误.

参数

verbosity

该参数表示使用高级输出错误信息详细级别,会将所有检查过的模板的错误全部输出.否则只会输出最近的查找到错误的文件信息.

break

遇到错误就直接输出不再继续检查

includes

通过参数 -i (可以重复使用)来添加自定义的模板目录

配置

VALIDATE_TEMPLATES_EXTRA_TEMPLATE_DIRS

通过 VALIDATE_TEMPLATES_EXTRA_TEMPLATE_DIRS 配置可以指定所有模板目录的前缀. 这个配置主要针对 TEMPLATE DIRS 是动态的或模板目录是通过中间件生成的情况. 扩展app的模板,比如Django项目中若是包含的 celery 模块 也可以通过指定该参数来进行模板语法检测.

用法举例

./manage.py validate_templates
[1]Django的单个版本指定了需要的Python版本,支持某个Django版本就代表同时支持相应的Python版本.