Django custom commands not found when built as .exe
dcabrero opened this issue · 1 comments
Describe the bug
When adding a Django custom admin command, it wont show or run by default when app is packaged.
To Reproduce
Start a basic boilerplate django app, then add a command:
https://docs.djangoproject.com/en/4.2/howto/custom-management-commands/
Expected behavior
After using setup.py build, should be able to run exename.exe custom_command
Desktop (please complete the following information):
- Platform information: Windows 10 pro x64
- Python 3.10.10
- cx_Freeze version: 6.15.15
- Django: 4.2.1
Additional context
I got it working by monkey patching this by importing this on my manage.py script.
def __override_commands():
import django.utils.autoreload
import django.core.management
original_commands = django.core.management.get_commands()
def _get_commands():
original_commands
commands = original_commands
commands['test_command'] = 'test_app'
return commands
_old_restart_with_reloader = django.utils.autoreload.restart_with_reloader
def _restart_with_reloader(*args):
import sys
a0 = sys.argv.pop(0)
try:
return _old_restart_with_reloader(*args)
finally:
sys.argv.insert(0, a0)
django.core.management.get_commands = _get_commands
django.utils.autoreload.restart_with_reloader = _restart_with_reloader
__override_commands()
del __override_commands
And making sure that setup.py has the command.py file in its build_options:
build_options = {
'packages': ['django', 'corsheaders', 'whitenoise', 'core_app', 'test_app'],
'includes': ['test_app.management.commands.test_command'],
'excludes': []
}
Hope it helps :]
Ok, after a few hours I noticed that even if were adding the package 'test_app', not all of its contents were going into the lib folder.
I'm now using this in my setup.py to get all the contents of a list of main folders that are part of a django project:
def get_py_files(directories):
py_files = []
for directory in directories:
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.py'):
relative_root = root.replace(directory, '').lstrip(os.sep)
dotted_path = relative_root.replace(os.sep, '.')
if dotted_path:
py_files.append(f"{directory}.{dotted_path}.{file[:-3]}")
else:
py_files.append(f"{directory}.{file[:-3]}")
return py_files
Probably not the cleanest way, but it works and auto detects the command without the previous solution I did before.