3

是否允许将自定义 Django 命令分组到同一 Django 应用程序中的单独文件夹?

我有很多,想按目的对它们进行逻辑分组。创建了文件夹,但 Django 找不到它们。

也许我试图错误地运行它们。试过:

  • python manage.py process_A_related_data
  • 同样的加上导入的所有命令__init__.py
  • python manage.py folderA process_A_related_data
  • python manage.py folderA.process_A_related_data
  • python manage.py folderA/process_A_related_data

出现以下错误:

Unknown command: 'folderA/process_A_related_data'
Type 'manage.py help' for usage.
4

4 回答 4

4

我认为您可以创建一个基本的自定义命令,该命令将从相关文件夹中运行其他命令。您可以采取以下方法:

首先制作一个这样的文件夹结构:

management/
    commands/
       folder_a/
          process_A_related_data.py
       folder_b/
          process_A_related_data.py
       process_data.py

然后在里面process_data.py,像这样更新命令:

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

import importlib

class Command(BaseCommand):
   help = 'Folder Process Commands'

   def add_arguments(self, parser):
       parser.add_argument('-u', '--use', type=str, nargs='?', default='folder_a.process_A_related_data')

   def handle(self, *args, **kwargs):
       try:
           folder_file_module = options['use'] if options['use'].startswith('.') else '.' + options['use']
           command = importlib.import_module(folder_file_module, package='your_app.management.commands')
           management.call_command(command.Command())
       except ModuleNotFoundError:
           self.stderr.write("No relevent folder found")

这里我使用call_command方法来调用其他管理命令。

然后运行如下命令:

python manage.py process_data --use folder_a.process_A_related_data

最后,如果您想运行类似的命令python manage.py folder_a.process_A_related_data,那么您可能需要更改manage.py. 像这样:

import re
...

try:
    from django.core.management import execute_from_command_line
except ImportError as exc:
    raise ImportError(
        "Couldn't import Django. Are you sure it's installed and "
        "available on your PYTHONPATH environment variable? Did you "
        "forget to activate a virtual environment?"
    ) from exc

if re.search('folder_[a-z].*', sys.argv[-1]):
    new_arguments = sys.argv[:-1] + ['process_data','--use', sys.argv[-1]]
    execute_from_command_line(new_arguments)
else:
    execute_from_command_line(sys.argv)
于 2020-03-10T07:04:46.727 回答
1

您应该能够使用 mixins 对代码进行分区(不过,我没有在这种情况下尝试过)

一个标准的管理命令看起来像

from django.core.management.base import BaseCommand

class Command(BaseCommand):
   help = 'FIXME A helpful comment goes here'

    def add_arguments(self, parser):
        parser.add_argument( 'name', ...)
        # more argument definitions

    def handle(self, *args, **options):  
        # do stuff

这可能可以被以下中的“存根”替换app/management/commands

from wherever.commands import FooCommandMixin
from django.core.management.base import BaseCommand    
class Command(FooCommandMixin, BaseCommand): 
    # autogenerated -- do not put any code in here!
    pass

并在任何地方/命令

class FooCommandMixin( object):
   help = 'FIXME A helpful comment goes here'

    def add_arguments(self, parser):
        parser.add_argument( 'name', ...)
        # more argument definitions

    def handle(self, *args, **options):  
        # do the work

编写一个脚本来遍历文件名或路径列表(使用 glob.glob)使用 re.findall 来识别适当的类声明,并为应用程序管理中的每个(重新)生成匹配的存根并不难/命令文件夹。

另外/相反,Python 的 argparse 允许定义 sub-commands。所以你应该能够定义一个像

./manage.py foo bar --aa --bb something --cc  and
./manage.py foo baz --bazzy a b c 

其中 foo 之后的语法由下一个单词(bar 或 baz 或 ...)确定。同样,我没有在这种情况下使用子命令的经验。

于 2020-03-04T10:15:35.307 回答
0

一种解决方法可能是:为每组管理命令创建一个特定的 Django“卫星”应用程序。

在最新版本的 Django 中,将 Python 模块作为应用程序的要求非常低:您不需要像过去那样提供任何虚假的 models.py 或其他特定文件。

虽然从风格的角度来看远非完美,但您仍然可以获得一些优势:

  • 根本不需要破解框架
  • python manage.py将列出按应用分组的命令
  • 您可以通过为应用程序提供合适的名称来控制分组
  • 您可以将这些附属应用程序用作特定单元测试的容器

我总是尽量避免与框架对抗,即使这意味着妥协,有时也接受它偶尔的设计限制。

于 2020-03-03T15:15:14.530 回答
0

我发现在发行说明中没有提到对此功能的支持。从 Django 3.0 版本开始,这似乎仍然不受支持。我建议您为有助于您指定的文件使用有意义的名称。你总是可以想出一个命名约定!

于 2020-03-03T14:34:35.837 回答