首页 > 其他分享 >django 1.8 官方文档翻译: 6-4-2 编写自定义的django-admin命令

django 1.8 官方文档翻译: 6-4-2 编写自定义的django-admin命令

时间:2023-04-13 14:36:00浏览次数:52  
标签:poll handle 自定义 admin app BaseCommand django 命令 Django


编写自定义的django-admin命令

应用可以通过manage.py注册它们自己的动作。例如,你可能想为你正在发布的Django应用添加一个manage.py动作。在本页文档中,我们将为教程中的 polls应用构建一个自定义的 closepoll命令。

要做到这点,只需向该应用添加一个management/commands目录。Django将为该目录中名字没有以下划线开始的每个Python模块注册一个manage.py命令。例如:

polls/
    __init__.py
    models.py
    management/
        __init__.py
        commands/
            __init__.py
            _private.py
            closepoll.py
    tests.py
    views.py

在Python 2上,请确保managementmanagement/commands两个目录都包含__init__.py 文件,否则将检测不到你的命令。

在这个例子中,closepoll命令对任何项目都可使用,只要它们在INSTALLED_APPS里包含polls应用。

_private.py将不可以作为一个管理命令使用。

closepoll.py模块只有一个要求 – 它必须定义一个Command类并扩展自BaseCommand或其 子类。

独立的脚本

自定义的管理命令主要用于运行独立的脚本或者UNIX crontab和Windows周期任务控制面板周期性执行的脚本。

要实现这个命令,需将polls/management/commands/closepoll.py编辑成这样:

from django.core.management.base import BaseCommand, CommandError
from polls.models import Poll

class Command(BaseCommand):
    help = 'Closes the specified poll for voting'

    def add_arguments(self, parser):
        parser.add_argument('poll_id', nargs='+', type=int)

    def handle(self, *args, **options):
        for poll_id in options['poll_id']:
            try:
                poll = Poll.objects.get(pk=poll_id)
            except Poll.DoesNotExist:
                raise CommandError('Poll "%s" does not exist' % poll_id)

            poll.opened = False
            poll.save()

            self.stdout.write('Successfully closed poll "%s"' % poll_id)
Changed in Django 1.8:

在Django 1.8之前,管理命令基于optparse模块,位置参数传递给*args,可选参数传递给**options。现在,管理命令使用argparse解析参数,默认所有的参数都传递给**options,除非你命名你的位置参数为args(兼容模式)。对于新的命令,鼓励你仅仅使用**options。

当你使用管理命令并希望提供控制台输出时,你应该写到self.stdoutself.stderr,而不能直接打印到 stdoutstderr。通过使用这些代理方法,测试你自定义的命令将变得非常容易。还请注意,你不需要在消息的末尾加上一个换行符,它将被自动添加,除非你指定ending参数:

self.stdout.write("Unterminated line", ending='')

>

新的自定义命令可以使用python manage.py closepoll <poll_id>调用。

handle()接收一个或多个poll_ids并为他们中的每个设置 poll.openedFalse。如果用户访问任何不存在的polls,将引发一个CommandErrorpoll.opened属性在教程中并不存在,只是为了这个例子将它添加到polls.models.Poll中。

接收可选参数

通过接收额外的命令行选项,可以简单地修改closepoll来删除一个给定的poll而不是关闭它。这些自定义的选项可以像下面这样添加到 add_arguments()方法中:

class Command(BaseCommand):
    def add_arguments(self, parser):
        # Positional arguments
        parser.add_argument('poll_id', nargs='+', type=int)

        # Named (optional) arguments
        parser.add_argument('--delete',
            action='store_true',
            dest='delete',
            default=False,
            help='Delete poll instead of closing it')

    def handle(self, *args, **options):
        # ...
        if options['delete']:
            poll.delete()
        # ...
Changed in Django 1.8:

之前,只支持标准的optparse库,你必须利用optparse.make_option()扩展命令option_list变量。

选项(在我们的例子中为delete)在handle方法的options字典参数中可以访问到。更多关于add_argument用法的信息,请参考argparse的Python 文档。

除了可以添加自定义的命令行选项, 管理命令还可以接收一些默认的选项,例如--verbosity--traceback

管理命令和区域设置

默认情况下,BaseCommand.execute()方法使转换失效,因为某些与Django一起的命令完成的任务要求一个与项目无关的语言字符串(例如,面向用户的内容渲染和数据库填入)。

Changed in Django 1.8:

在之前的版本中,Django强制使用"en-us"区域设置而不是使转换失效。

如果,出于某些原因,你的自定义的管理命令需要使用一个固定的区域设置,你需要在你的handle()方法中利用I18N支持代码提供的函数手工地启用和停用它:

from django.core.management.base import BaseCommand, CommandError
from django.utils import translation

class Command(BaseCommand):
    ...
    can_import_settings = True

    def handle(self, *args, **options):

        # Activate a fixed locale, e.g. Russian
        translation.activate('ru')

        # Or you can activate the LANGUAGE_CODE # chosen in the settings:
        from django.conf import settings
        translation.activate(settings.LANGUAGE_CODE)

        # Your command logic here
        ...

        translation.deactivate()

另一个需要可能是你的命令只是简单地应该使用设置中设置的区域设置且Django应该保持不让它停用。你可以使用BaseCommand.leave_locale_alone选项实现这个功能。

虽然上面描述的场景可以工作,但是考虑到系统管理命令对于运行非统一的区域设置通常必须非常小心,所以你可能需要:

  • 确保运行命令时USE_I18N设置永远为True(this is a good example of the potential problems stemming from a dynamic runtime environment that Django commands avoid offhand by deactivating translations)。
  • Review the code of your command and the code it calls for behavioral differences when locales are changed and evaluate its impact on predictable behavior of your command.

测试

关于如何测试自定义管理命令的信息可以在测试文档中找到。

Command 对象

class BaseCommand

所有管理命令最终继承的基类。

如果你想获得解析命令行参数并在响应中如何调用代码的所有机制,可以使用这个类;如果你不需要改变这个行为,请考虑使用它的子类。

继承BaseCommand类要求你实现handle()方法。

属性

所有的属性都可以在你派生的类中设置,并在BaseCommand的子类中使用。

BaseCommand.args

一个字符串,列出命令接收的参数,适合用于帮助信息;例如,接收一个应用名称列表的命令可以设置它为‘<app_label app_label ...>’。

Deprecated since version 1.8:

现在,应该在add_arguments()方法中完成,通过调用parser.add_argument()方法。参见上面的closepoll例子。

BaseCommand.can_import_settings

一个布尔值,指示该命令是否需要导入Django的设置的能力;如果为Trueexecute()将在继续之前验证这是否可能。默认值为True

BaseCommand.help

命令的简短描述,当用户运行python manage.py help <command>命令时将在帮助信息中打印出来。

BaseCommand.missing_args_message

New in Django 1.8.

如果你的命令定义了必需的位置参数,你可以自定义参数缺失时返回的错误信息。默认是由argparse输出的 (“too few arguments”)。

BaseCommand.option_list

这是optparse选项列表,将赋值给命令的OptionParser用于解析命令。

Deprecated since version 1.8:

现在,你应该覆盖`add_arguments()`方法来添加命令行接收的自定义参数。参见上面的例子。

BaseCommand.output_transaction

一个布尔值,指示命令是否输出SQL语句;如果为True,输出将被自动用BEGIN;COMMIT;封装。默认为False

BaseCommand.requires_system_checks

New in Django 1.7.

一个布尔值;如果为True,在执行该命令之前将检查整个Django项目是否有潜在的问题。如果requires_system_checks缺失,则使用requires_model_validation的值。如果后者的值也缺失,则使用默认值(True)。同时定义requires_system_checksrequires_model_validation将导致错误。

BaseCommand.requires_model_validation

Deprecated since version 1.7:

被requires_system_checks代替

一个布尔值;如果为True,将在执行命令之前作安装的模型的验证。默认为True。若要验证一个单独应用的模型而不是全部应用的模型,可以调用在handle()中调用validate()

BaseCommand.leave_locale_alone

一个布尔值,指示设置中的区域设置在执行命令过程中是否应该保持而不是强制设成‘en-us’。

默认值为False

如果你决定在你自定义的命令中修改该选项的值,请确保你知道你正在做什么。 如果它创建对区域设置敏感的数据库内容,这种内容不应该包含任何转换(比如django.contrib.auth权限发生的情况),因为将区域设置变成与实际上默认的‘en-us’ 不同可能导致意外的效果。更进一步的细节参见上面的管理命令和区域设置一节。

can_import_settings选项设置为False时,该选项不可以也为False,因为尝试设置区域设置需要访问settings。这种情况将产生一个CommandError

方法

BaseCommand有几个方法可以被覆盖,但是只有handle()是必须实现的。

在子类中实现构造函数

如果你在BaseCommand的子类中实现__init__,你必须调用BaseCommand__init__

class Command(BaseCommand):
    def __init__(self, *args, **kwargs):
        super(Command, self).__init__(*args, **kwargs)
        # ...

>

BaseCommand.add_arguments(parser)

New in Django 1.8.

添加解析器参数的入口,以处理传递给命令的命令行参数。自定义的命令应该覆盖这个方法以添加命令行接收的位置参数和可选参数。当直接继承BaseCommand时不需要调用super()

BaseCommand.get_version()

返回Django的版本,对于所有内建的Django命令应该都是正确的。用户提供的命令可以覆盖这个方法以返回它们自己的版本。

BaseCommand.execute(*args, **options)

执行这个命令,如果需要则作系统检查(通过 requires_system_checks属性控制)。如果该命令引发一个CommandError,它将被截断并打印到标准错误输出。

在你的代码中调用管理命令

不应该在你的代码中直接调用execute()来执行一个命令。请使用call_command

BaseCommand.handle(*args, **options)

命令的真正逻辑。子类必须实现这个方法。

BaseCommand.check(app_configs=None, tags=None, display_num_errors=False)

New in Django 1.7.

利用系统的检测框架检测全部Django项目的潜在问题。严重的问题将引发CommandError;警告会输出到标准错误输出;次要的通知会输出到标准输出。

如果app_configstags都为None,将进行所有的系统检查。tags可以是一个要检查的标签列表,比如compatibilitymodels

BaseCommand.validate(app=None, display_num_errors=False)

Deprecated since version 1.7:

被check命令代替

如果appNone,那么将检查安装的所有应用的错误。

BaseCommand 的子类

class AppCommand

这个管理命令接收一个或多个安装的应用标签作为参数,并对它们每一个都做一些动作。

子类不用实现handle(),但必须实现handle_app_config(),它将会为每个应用调用一次。

AppCommand.handle_app_config(app_config, **options)

app_config完成命令行的动作,其中app_configAppConfig的实例,对应于在命令行上给出的应用标签。

Changed in Django 1.7:

以前,AppCommand子类必须实现handle_app(app, **options),其中app是一个模型模块。新的API可以不需要模型模块来处理应用。迁移的最快的方法如下:

def handle_app_config(app_config, **options):
    if app_config.models_module is None:
        return                                  # Or raise an exception.
    app = app_config.models_module
    # Copy the implementation of handle_app(app_config, **options) here.

>

然而,你可以通过直接使用app_config的属性来简化实现。

class LabelCommand

这个管理命令接收命令行上的一个或多个参数(标签),并对它们每一个都做一些动作。

子类不用实现handle(),但必须实现handle_label(),它将会为每个标签调用一次。

LabelCommand.handle_label(label, **options)

label完成命令行的动作,label是命令行给出的字符串。

class NoArgsCommand

Deprecated since version 1.8:

使用BaseCommand代替,它默认也不需要参数。

这个命令不接收命令行上的参数。

子类不需要实现handle(),但必须实现handle_noargs()handle()本身已经被覆盖以保证不会有参数传递给命令。

NoArgsCommand.handle_noargs(**options)

完成这个命令的动作

Command 的异常

class CommandError

异常类,表示执行一个管理命令时出现问题。

如果这个异常是在执行一个来自命令行控制台的管理命令时引发,它将被捕获并转换成一个友好的错误信息到合适的输出流(例如,标准错误输出);因此,引发这个异常(并带有一个合理的错误描述)是首选的方式来指示在执行一个命令时某些东西出现错误。

如果管理命令从代码中通过call_command调用,那么需要时捕获这个异常由你决定。

译者:Django 文档协作翻译小组,原文:Adding custom commands

本文以 CC BY-NC-SA 3.0 协议发布,转载请保留作者署名和文章出处。

Django 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质。交流群:467338606。

标签:poll,handle,自定义,admin,app,BaseCommand,django,命令,Django
From: https://blog.51cto.com/wizardforcel/6187984

相关文章

  • django 1.8 官方文档翻译: 6-6-2 如何使用WSGI 部署
    如何使用WSGI部署Django首要的部署平台是WSGI,它是PythonWeb服务器和应用的标准。Django的startproject管理命名为你设置一个简单的默认WSGI配置,你可以根据你项目的需要做调整并指定任何与WSGI兼容的应用服务器使用。Django包含以下WSGI服务器的入门文档:如何使用Apache和......
  • django 1.8 官方文档翻译:6-5-1 Django中的测试
    Django中的测试自动化测试对于现代web开发者来说,是非常实用的除错工具。你可以使用一系列测试–测试套件–来解决或者避免大量问题:当你编写新代码的时候,你可以使用测试来验证你的代码是否像预期一样工作。当你重构或者修改旧代码的时候,你可以使用测试来确保你的修改不会在意料之......
  • django 1.8 官方文档翻译:2-5-9 条件表达式
    条件表达式NewinDjango1.8.条件表达式允许你在过滤器、注解、聚合和更新操作中使用if...elif...else的逻辑。条件表达式为表中的每一行计算一系列的条件,并且返回匹配到的结果表达式。条件表达式也可以像其它表达式一样混合和嵌套。条件表达式类我们会在后面的例子中使用下......
  • django 1.8 官方文档翻译: 2-5-7 自定义查找
    自定义查找NewinDjango1.7.Django为过滤提供了大量的内建的查找(例如,exact和icontains)。这篇文档阐述了如何编写自定义查找,以及如何修改现存查找的功能。关于查找的API参考,详见查找API参考。一个简单的查找示例让我们从一个简单的自定义查找开始。我们会编写一个自定义查找ne,提供......
  • django 1.8 官方文档翻译: 2-5-10 数据库函数
    数据库函数NewinDjango1.8.下面记述的类为用户提供了一些方法,来在Django中使用底层数据库提供的函数用于注解、聚合或者过滤器等操作。函数也是表达式,所以可以像聚合函数一样混合使用它们。我们会在每个函数的实例中使用下面的模型:classAuthor(models.Model):name=model......
  • django 1.8 官方文档翻译: 3-3-4 管理文件
    管理文件这篇文档描述了Django为那些用户上传文件准备的文件访问API。底层的API足够通用,你可以使用为其它目的来使用它们。如果你想要处理静态文件(JS,CSS,以及其他),参见管理静态文件(CSS和图像)。通常,Django使用MEDIA_ROOT和MEDIA_URL设置在本地储存文件。下面的例子假设你使用这些默认......
  • Cesium的搜索框如何自定义功能
    geocoder提供了地理编码功能用来搜索位置,但是在离线环境下无法使用。为了将这个搜索框用起来,添加根据坐标搜索的功能,可以这么写:viewer.geocoder._form.children[0].placeholder="请输入:经度,纬度";viewer.geocoder.autoComplete=false;functionmyGeocoder(){......
  • WPF 自定义控件 二次渲染 问题记录
    问题将多个自定义控件加载到到一个页面的Grid上显示。然后突然将一个控件从Grid里面清除,控件依然在后台处理数据。过段时间再加入Grid。然后一些已经改变的页面属性就消失了。原因经过查找是一旦控件再次加载,页面属性就会重置。这个有利也有弊端。1是可以利用这点重置页面2......
  • linux系统自定义登录提示信息
    配置说明这里对于centos7.x系统,可以直接编辑/etc/motd文件,增加定制的提示信息,并可以通过不同颜色展示。vim/etc/motd^[[32m设备IP地址:10.10.10.22^[[0m^[[32m使用人员:zhangshan^[[0m^[[31m注意:其它人员使用请和使用人确认^[[0m#注意,如果需要增加展示信息,可以......
  • Django 对实体的增删改查样例
    classUserInfo(models.Model):"""人员信息"""user_id=models.CharField(max_length=20,primary_key=True,blank=False,verbose_name='人员ID')user_name=models.CharField(max_length=200,blank=Fal......