Repository: pyinstaller/pyinstaller

Issue:
Fixes for use of pyinstaller with Django 4.x and custom management commands.
PROBLEM:
This feature aims to solve the problem of the custom app level management commands being missed out from hidden imports alongside issues with imports of apps listed within INSTALLED_APPS failing due to erroneous execution of 'eval_script' function. Specifically when the hidden imports of the INSTALLED_APPS are evaluated the logging outputs generated by 'collect_submodules' when called in django_import_finder.py are captured in the STDOUT regardless of the --log-level. Also any additional management commands provided by one of the INSTALLED_APPS are ignored as the 'get_commands' function has a hardcoded referenced to Django 1.8 command set. Django's currently implementation of command collection will not complain of missing commands at runtime thereby rendering the patch of this function that is currently implemented irrelevant.

SOLUTION:
The solution to this issue is to remove several redundant parts of the code alongside adding additional overrides for decluttering STDOUT. 

The following is a list of measures taken to resolve the problem
-  remove the monkey patching of Django's 'get_commands' method in pyi_rth_django.py
- modify the collect static code to have a boolean input parameter 'log' which when the relevant calls to logging within this function are wrapped in a conditional will serve to prevent logs being inappropriately raised.



Discussion:
Neither of us have any experience with django, nor do we feel that PyInstaller+django is a particularly wise combination. If you want this to happen, you'll have to do it yourself.

Resolving patch:
diff --git a/PyInstaller/hooks/rthooks/pyi_rth_django.py b/PyInstaller/hooks/rthooks/pyi_rth_django.py
--- a/PyInstaller/hooks/rthooks/pyi_rth_django.py
+++ b/PyInstaller/hooks/rthooks/pyi_rth_django.py
@@ -11,54 +11,8 @@
 
 # This Django rthook was tested with Django 1.8.3.
 
-import django.core.management
 import django.utils.autoreload
 
-
-def _get_commands():
-    # Django groupss commands by app. This returns static dict() as it is for django 1.8 and the default project.
-    commands = {
-        'changepassword': 'django.contrib.auth',
-        'check': 'django.core',
-        'clearsessions': 'django.contrib.sessions',
-        'collectstatic': 'django.contrib.staticfiles',
-        'compilemessages': 'django.core',
-        'createcachetable': 'django.core',
-        'createsuperuser': 'django.contrib.auth',
-        'dbshell': 'django.core',
-        'diffsettings': 'django.core',
-        'dumpdata': 'django.core',
-        'findstatic': 'django.contrib.staticfiles',
-        'flush': 'django.core',
-        'inspectdb': 'django.core',
-        'loaddata': 'django.core',
-        'makemessages': 'django.core',
-        'makemigrations': 'django.core',
-        'migrate': 'django.core',
-        'runfcgi': 'django.core',
-        'runserver': 'django.core',
-        'shell': 'django.core',
-        'showmigrations': 'django.core',
-        'sql': 'django.core',
-        'sqlall': 'django.core',
-        'sqlclear': 'django.core',
-        'sqlcustom': 'django.core',
-        'sqldropindexes': 'django.core',
-        'sqlflush': 'django.core',
-        'sqlindexes': 'django.core',
-        'sqlmigrate': 'django.core',
-        'sqlsequencereset': 'django.core',
-        'squashmigrations': 'django.core',
-        'startapp': 'django.core',
-        'startproject': 'django.core',
-        'syncdb': 'django.core',
-        'test': 'django.core',
-        'testserver': 'django.core',
-        'validate': 'django.core'
-    }
-    return commands
-
-
 _old_restart_with_reloader = django.utils.autoreload.restart_with_reloader
 
 
@@ -71,8 +25,6 @@ def _restart_with_reloader(*args):
         sys.argv.insert(0, a0)
 
 
-# Override get_commands() function otherwise the app will complain that there are no commands.
-django.core.management.get_commands = _get_commands
 # Override restart_with_reloader() function, otherwise the app might complain that some commands do not exist;
 # e.g., runserver.
 django.utils.autoreload.restart_with_reloader = _restart_with_reloader


Test patch: