Django自定义命令 - 初学者教程

199 阅读2分钟

编码员你好。

本文介绍了如何编写我们自己的Django自定义命令,这些命令可能会帮助我们在生产环境中对Django项目进行测试、上传数据或提取有价值的信息。对于新手来说,Django是一个流行的网络框架,由经验丰富的开发人员用Python设计和编写。自定义命令的主要优势在于,所有的Django机器都已加载并准备好使用。这意味着你可以导入模型,使用Django的ORM执行对数据库的查询,并与你项目的所有资源互动。

谢谢你的阅读!- 内容由**App Generator**提供。

涉及的主题

  • 创建一个新的Django应用程序并更新Django以使用它
  • 可视化应用程序内部所需的目录结构
  • 代码端执行一些自定义命令。
    • cmd_time.py - 显示当前的时间戳
    • cmd_apps - 列出所有已注册的应用程序
    • cmd_models - 列出所有应用程序和相关模型
    • cmd_showcfg - 列出所有CFG键和值
  • 源代码可以在Github上找到(MIT许可)。

创建一个新的Django应用程序

本教程假设我们有一个正在工作的Django项目,我们将继续前进,通过startapp 子命令创建一个新的应用程序。

$ python manage.py startapp app_customcmd

在新的app 目录内,我们需要创建一个目录结构,如下图所示。

< PROJECT ROOT >                          <-- project directory
 |
 |-- app_customcmd/                                <-- app directory
 |    |-- management/
 |    |    +-- __init__.py
 |    |    +-- commands/
 |    |         +-- __init__.py
 |    |         +-- cmd_....py  <-- module where all commands are saved

一旦我们建立并配置Django使用新的应用程序,即使不重启应用程序,也会自动发现commands 目录中定义的所有命令。

配置Django以使用该应用程序

为了执行我们的自定义命令,我们需要在项目配置中激活app_customcmd

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app_customcmd',               # <-- NEW
] 

自定义命令

本节介绍的自定义命令将访问和报告一些与Django项目内部相关的东西--让我们开始吧!

显示当前时间

这个简单的自定义命令帮助我们适应这个概念。这里是代码,保存在app_customcmd/management/commands 目录中。

from django.core.management.base import BaseCommand
from django.utils import timezone

class Command(BaseCommand):
    help = 'Displays current time'

    def handle(self, *args, **kwargs):
        time = timezone.now().strftime('%X')
        self.stdout.write("It's %s" % time)

实际执行的代码位于handle 方法中,执行时应该显示与此类似的内容。

$ python manage.py cmd_time
It's 09:18:08                <-- The output from our custom CMD

关于代码的最重要的方面是使用BaseCommand 作为我们定义的超类。

显示已注册的应用程序

这个例子将遍历所有注册和活动的应用程序并打印它们的名字。

from django.core.management.base import BaseCommand
from django.apps import apps

class Command(BaseCommand):
    help = 'Displays registered apps'

    def handle(self, *args, **kwargs):
        for app in apps.get_app_configs():
            self.stdout.write(" APP -> %s" % app.verbose_name)

脚本执行和输出。

$ python manage.py cmd_apps
 APP -> Administration                     # Default Django App   
 APP -> Authentication and Authorization   # Default Django App
 APP -> Content Types                      # Default Django App
 APP -> Sessions                           # Default Django App
 APP -> Messages                           # Default Django App
 APP -> Static Files                       # Default Django App
 APP -> App_Customcmd                      # <-- Our NEW App   

显示每个应用程序的模型

这个命令与之前的命令很相似,但也提供每个应用程序的注册模型。

from django.core.management.base import BaseCommand

from django.apps import apps

class Command(BaseCommand):
    help = 'Displays registered apps and models'

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

        # Iterate over apps
        for app in apps.get_app_configs():
            self.stdout.write(" APP -> %s" % app.verbose_name)

            # Iterate over models                                # <-- New Code 
            for model in app.get_models():                       # <-- New Code 
                self.stdout.write("\t |- (model) -> %s" % model) # <-- New Code

执行和输出

$ python manage.py cmd_models
 APP -> Administration
         |- (model) -> <class 'django.contrib.admin.models.LogEntry'>
 APP -> Authentication and Authorization
         |- (model) -> <class 'django.contrib.auth.models.Permission'>
         |- (model) -> <class 'django.contrib.auth.models.Group'>
         |- (model) -> <class 'django.contrib.auth.models.User'>
 APP -> Content Types
         |- (model) -> <class 'django.contrib.contenttypes.models.ContentType'>
 APP -> Sessions
         |- (model) -> <class 'django.contrib.sessions.models.Session'>        
 APP -> Messages
 APP -> Static Files
 APP -> App_Forms
 APP -> App_Pdf
 APP -> App_Customcmd
 APP -> App
         |- (model) -> <class 'app.models.Book'>

打印配置变量

这个自定义命令扫描settings 对象的属性并打印所有值。

from django.core.management.base import BaseCommand
from django.utils import timezone

from django.conf import settings

class Command(BaseCommand):
    help = 'Displays project config'

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

        # type( settings ) => <class 'django.conf.LazySettings'>
        # settings.__dict__

        # Iterate over apps
        for key in settings.__dict__.keys():

            self.stdout.write(" Cfg Key: " + key + " -> %s" % settings.__dict__[ key ] )

输出和执行。

(env) PS D:\work\repo-samples\django-learn-by-coding> python manage.py cmd_showcfg
 Cfg Key: _wrapped -> <Settings "config.settings">
 Cfg Key: INSTALLED_APPS -> ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app_forms', 'app_pdf', 'app_customcmd', 'app']
 Cfg Key: DEBUG -> True
 Cfg Key: LOGGING_CONFIG -> logging.config.dictConfig
 Cfg Key: LOGGING -> {}
 Cfg Key: DEFAULT_EXCEPTION_REPORTER -> django.views.debug.ExceptionReporter
 Cfg Key: FORCE_SCRIPT_NAME -> None
 Cfg Key: DEFAULT_TABLESPACE ->
 Cfg Key: DEFAULT_AUTO_FIELD -> django.db.models.BigAutoField
 Cfg Key: ABSOLUTE_URL_OVERRIDES -> {}
 Cfg Key: AUTH_USER_MODEL -> auth.User
 Cfg Key: DATABASES -> {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': WindowsPath('D:/work/repo-samples/django-learn-by-coding/db.sqlite3'), 'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_MAX_AGE': 0, 'OPTIONS': {}, 'TIME_ZONE': None, 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', 'TEST': {'CHARSET': None, 'COLLATION': None, 'MIGRATE': True, 'MIRROR': None, 'NAME': None}}}
...
(truncated output)

在我们的Django项目中编写自定义命令可能有助于我们提取统计数据、执行cron作业,以及检查在生产中运行的项目的健康状况。

谢谢你的阅读!更多资源和支持,请随时访问。