Fixed #32309 -- Added --exclude option to startapp/startproject management commands.
This commit is contained in:
parent
3686077d46
commit
84c7c4a477
|
@ -1,3 +1,4 @@
|
|||
import argparse
|
||||
import cgi
|
||||
import mimetypes
|
||||
import os
|
||||
|
@ -54,6 +55,14 @@ class TemplateCommand(BaseCommand):
|
|||
help='The file name(s) to render. Separate multiple file names '
|
||||
'with commas, or use -n multiple times.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--exclude', '-x',
|
||||
action='append', default=argparse.SUPPRESS, nargs='?', const='',
|
||||
help=(
|
||||
'The directory name(s) to exclude, in addition to .git and '
|
||||
'__pycache__. Can be used multiple times.'
|
||||
),
|
||||
)
|
||||
|
||||
def handle(self, app_or_project, name, target=None, **options):
|
||||
self.app_or_project = app_or_project
|
||||
|
@ -82,8 +91,12 @@ class TemplateCommand(BaseCommand):
|
|||
|
||||
extensions = tuple(handle_extensions(options['extensions']))
|
||||
extra_files = []
|
||||
excluded_directories = ['.git', '__pycache__']
|
||||
for file in options['files']:
|
||||
extra_files.extend(map(lambda x: x.strip(), file.split(',')))
|
||||
if exclude := options.get('exclude'):
|
||||
for directory in exclude:
|
||||
excluded_directories.append(directory.strip())
|
||||
if self.verbosity >= 2:
|
||||
self.stdout.write(
|
||||
'Rendering %s template files with extensions: %s'
|
||||
|
@ -126,8 +139,11 @@ class TemplateCommand(BaseCommand):
|
|||
os.makedirs(target_dir, exist_ok=True)
|
||||
|
||||
for dirname in dirs[:]:
|
||||
if 'exclude' not in options:
|
||||
if dirname.startswith('.') or dirname == '__pycache__':
|
||||
dirs.remove(dirname)
|
||||
elif dirname in excluded_directories:
|
||||
dirs.remove(dirname)
|
||||
|
||||
for filename in files:
|
||||
if filename.endswith(('.pyo', '.pyc', '.py.class')):
|
||||
|
|
|
@ -1304,6 +1304,14 @@ Specifies which files in the app template (in addition to those matching
|
|||
``--extension``) should be rendered with the template engine. Defaults to an
|
||||
empty list.
|
||||
|
||||
.. django-admin-option:: --exclude DIRECTORIES, -x DIRECTORIES
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
Specifies which directories in the app template should be excluded, in addition
|
||||
to ``.git`` and ``__pycache__``. If this option is not provided, directories
|
||||
named ``__pycache__`` or starting with ``.`` will be excluded.
|
||||
|
||||
The :class:`template context <django.template.Context>` used for all matching
|
||||
files is:
|
||||
|
||||
|
@ -1373,6 +1381,14 @@ Specifies which files in the project template (in addition to those matching
|
|||
``--extension``) should be rendered with the template engine. Defaults to an
|
||||
empty list.
|
||||
|
||||
.. django-admin-option:: --exclude DIRECTORIES, -x DIRECTORIES
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
Specifies which directories in the project template should be excluded, in
|
||||
addition to ``.git`` and ``__pycache__``. If this option is not provided,
|
||||
directories named ``__pycache__`` or starting with ``.`` will be excluded.
|
||||
|
||||
The :class:`template context <django.template.Context>` used is:
|
||||
|
||||
- Any option passed to the ``startproject`` command (among the command's
|
||||
|
|
|
@ -278,6 +278,9 @@ Management Commands
|
|||
<django.core.management.BaseCommand.suppressed_base_arguments>` attribute
|
||||
allows suppressing unsupported default command options in the help output.
|
||||
|
||||
* The new :option:`startapp --exclude` and :option:`startproject --exclude`
|
||||
options allow excluding directories from the template.
|
||||
|
||||
Migrations
|
||||
~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -2232,6 +2232,70 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase):
|
|||
hidden_dir = os.path.join(testproject_dir, '.hidden')
|
||||
self.assertIs(os.path.exists(hidden_dir), False)
|
||||
|
||||
def test_custom_project_template_hidden_directory_included(self):
|
||||
"""
|
||||
Template context variables in hidden directories are rendered, if not
|
||||
excluded.
|
||||
"""
|
||||
template_path = os.path.join(custom_templates_dir, 'project_template')
|
||||
project_name = 'custom_project_template_hidden_directories_included'
|
||||
args = [
|
||||
'startproject',
|
||||
'--template',
|
||||
template_path,
|
||||
project_name,
|
||||
'project_dir',
|
||||
'--exclude',
|
||||
]
|
||||
testproject_dir = os.path.join(self.test_dir, 'project_dir')
|
||||
os.mkdir(testproject_dir)
|
||||
|
||||
_, err = self.run_django_admin(args)
|
||||
self.assertNoOutput(err)
|
||||
render_py_path = os.path.join(testproject_dir, '.hidden', 'render.py')
|
||||
with open(render_py_path) as fp:
|
||||
self.assertIn(
|
||||
f'# The {project_name} should be rendered.',
|
||||
fp.read(),
|
||||
)
|
||||
|
||||
def test_custom_project_template_exclude_directory(self):
|
||||
"""
|
||||
Excluded directories (in addition to .git and __pycache__) are not
|
||||
included in the project.
|
||||
"""
|
||||
template_path = os.path.join(custom_templates_dir, 'project_template')
|
||||
project_name = 'custom_project_with_excluded_directories'
|
||||
args = [
|
||||
'startproject',
|
||||
'--template',
|
||||
template_path,
|
||||
project_name,
|
||||
'project_dir',
|
||||
'--exclude',
|
||||
'additional_dir',
|
||||
'-x',
|
||||
'.hidden',
|
||||
]
|
||||
testproject_dir = os.path.join(self.test_dir, 'project_dir')
|
||||
os.mkdir(testproject_dir)
|
||||
|
||||
_, err = self.run_django_admin(args)
|
||||
self.assertNoOutput(err)
|
||||
excluded_directories = [
|
||||
'.hidden',
|
||||
'additional_dir',
|
||||
'.git',
|
||||
'__pycache__',
|
||||
]
|
||||
for directory in excluded_directories:
|
||||
self.assertIs(
|
||||
os.path.exists(os.path.join(testproject_dir, directory)),
|
||||
False,
|
||||
)
|
||||
not_excluded = os.path.join(testproject_dir, project_name)
|
||||
self.assertIs(os.path.exists(not_excluded), True)
|
||||
|
||||
|
||||
class StartApp(AdminScriptTestCase):
|
||||
|
||||
|
|
Loading…
Reference in New Issue