Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #15372 -- Switched to a startproject default layout that allows…

… us to avoid sys.path hacks.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16964 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 38f1fe3b35c212136d959538a309c33bf2d340a9 1 parent f04af70
Carl Meyer authored October 13, 2011
17  django/conf/project_template/manage.py
... ...
@@ -1,14 +1,9 @@
1 1
 #!/usr/bin/env python
2  
-from django.core.management import execute_manager
3  
-import imp
4  
-try:
5  
-    imp.find_module('settings') # Assumed to be in the same directory.
6  
-except ImportError:
7  
-    import sys
8  
-    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
9  
-    sys.exit(1)
10  
-
11  
-import settings
  2
+import os, sys
12 3
 
13 4
 if __name__ == "__main__":
14  
-    execute_manager(settings)
  5
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
  6
+
  7
+    from django.core.management import execute_from_command_line
  8
+
  9
+    execute_from_command_line(sys.argv)
0  django/conf/project_template/__init__.py → ...go/conf/project_template/project_name/__init__.py
File renamed without changes
0  django/conf/project_template/settings.py → ...go/conf/project_template/project_name/settings.py
File renamed without changes
0  django/conf/project_template/urls.py → django/conf/project_template/project_name/urls.py
File renamed without changes
34  django/core/management/__init__.py
@@ -2,6 +2,7 @@
2 2
 import sys
3 3
 from optparse import OptionParser, NO_DEFAULT
4 4
 import imp
  5
+import warnings
5 6
 
6 7
 import django
7 8
 from django.core.management.base import BaseCommand, CommandError, handle_default_options
@@ -102,14 +103,6 @@ def get_commands():
102 103
         except (AttributeError, EnvironmentError, ImportError):
103 104
             apps = []
104 105
 
105  
-        # Find the project directory
106  
-        try:
107  
-            from django.conf import settings
108  
-            module = import_module(settings.SETTINGS_MODULE)
109  
-            project_directory = setup_environ(module, settings.SETTINGS_MODULE)
110  
-        except (AttributeError, EnvironmentError, ImportError, KeyError):
111  
-            project_directory = None
112  
-
113 106
         # Find and load the management module for each installed app.
114 107
         for app_name in apps:
115 108
             try:
@@ -119,17 +112,6 @@ def get_commands():
119 112
             except ImportError:
120 113
                 pass # No management module - ignore this app
121 114
 
122  
-        if project_directory:
123  
-            # Remove the "startproject" command from self.commands, because
124  
-            # that's a django-admin.py command, not a manage.py command.
125  
-            del _commands['startproject']
126  
-
127  
-            # Override the startapp command so that it always uses the
128  
-            # project_directory, not the current working directory
129  
-            # (which is default).
130  
-            from django.core.management.commands.startapp import ProjectCommand
131  
-            _commands['startapp'] = ProjectCommand(project_directory)
132  
-
133 115
     return _commands
134 116
 
135 117
 def call_command(name, *args, **options):
@@ -388,6 +370,13 @@ def setup_environ(settings_mod, original_settings_path=None):
388 370
     The "original_settings_path" parameter is optional, but recommended, since
389 371
     trying to work out the original path from the module can be problematic.
390 372
     """
  373
+    warnings.warn(
  374
+        "The 'setup_environ' function is deprecated, "
  375
+        "you likely need to update your 'manage.py'; "
  376
+        "please see the Django 1.4 release notes "
  377
+        "(https://docs.djangoproject.com/en/dev/releases/1.4/).",
  378
+        PendingDeprecationWarning)
  379
+
391 380
     # Add this project to sys.path so that it's importable in the conventional
392 381
     # way. For example, if this file (manage.py) lives in a directory
393 382
     # "myproject", this code would add "/path/to/myproject" to sys.path.
@@ -437,6 +426,13 @@ def execute_manager(settings_mod, argv=None):
437 426
     Like execute_from_command_line(), but for use by manage.py, a
438 427
     project-specific django-admin.py utility.
439 428
     """
  429
+    warnings.warn(
  430
+        "The 'execute_manager' function is deprecated, "
  431
+        "you likely need to update your 'manage.py'; "
  432
+        "please see the Django 1.4 release notes "
  433
+        "(https://docs.djangoproject.com/en/dev/releases/1.4/).",
  434
+        PendingDeprecationWarning)
  435
+
440 436
     setup_environ(settings_mod)
441 437
     utility = ManagementUtility(argv)
442 438
     utility.execute()
4  django/core/management/commands/startproject.py
@@ -15,8 +15,6 @@ class Command(LabelCommand):
15 15
     can_import_settings = False
16 16
 
17 17
     def handle_label(self, project_name, **options):
18  
-        # Determine the project_name a bit naively -- by looking at the name of
19  
-        # the parent directory.
20 18
         directory = os.getcwd()
21 19
 
22 20
         # Check that the project_name cannot be imported.
@@ -30,7 +28,7 @@ def handle_label(self, project_name, **options):
30 28
         copy_helper(self.style, 'project', project_name, directory)
31 29
 
32 30
         # Create a random SECRET_KEY hash, and put it in the main settings.
33  
-        main_settings_file = os.path.join(directory, project_name, 'settings.py')
  31
+        main_settings_file = os.path.join(directory, project_name, project_name, 'settings.py')
34 32
         settings_contents = open(main_settings_file, 'r').read()
35 33
         fp = open(main_settings_file, 'w')
36 34
         secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
5  docs/internals/deprecation.txt
@@ -246,6 +246,11 @@ these changes.
246 246
 
247 247
     * The Databrowse contrib module will be removed.
248 248
 
  249
+    * The functions :func:`~django.core.management.setup_environ` and
  250
+      :func:`~django.core.management.execute_manager` will be removed from
  251
+      :mod:`django.core.management`. This also means that the old (pre-1.4)
  252
+      style of :file:`manage.py` file will no longer work.
  253
+
249 254
 2.0
250 255
 ---
251 256
 
87  docs/intro/tutorial01.txt
@@ -90,41 +90,58 @@ within your Python installation. Consider symlinking to :doc:`django-admin.py
90 90
 Let's look at what :djadmin:`startproject` created::
91 91
 
92 92
     mysite/
93  
-        __init__.py
94 93
         manage.py
95  
-        settings.py
96  
-        urls.py
  94
+        mysite/
  95
+            __init__.py
  96
+            settings.py
  97
+            urls.py
  98
+
  99
+.. admonition:: Doesn't match what you see?
  100
+
  101
+    The default project layout recently changed. If you're seeing a "flat"
  102
+    layout (with no inner :file:`mysite/` directory), you're probably using
  103
+    a version of Django that doesn't match this tutorial version.  You'll
  104
+    want to either switch to the older tutorial or the newer Django version.
97 105
 
98 106
 These files are:
99 107
 
100  
-    * :file:`__init__.py`: An empty file that tells Python that this directory
101  
-      should be considered a Python package. (Read `more about packages`_ in the
102  
-      official Python docs if you're a Python beginner.)
  108
+* The outer :file:`mysite/` directory is just a container for your
  109
+  project. Its name doesn't matter to Django; you can rename it to anything
  110
+  you like.
  111
+
  112
+* :file:`manage.py`: A command-line utility that lets you interact with this
  113
+  Django project in various ways. You can read all the details about
  114
+  :file:`manage.py` in :doc:`/ref/django-admin`.
103 115
 
104  
-    * :file:`manage.py`: A command-line utility that lets you interact with this
105  
-      Django project in various ways. You can read all the details about
106  
-      :file:`manage.py` in :doc:`/ref/django-admin`.
  116
+* The inner :file:`mysite/` directory is the actual Python package for your
  117
+  project. Its name is the Python package name you'll need to use to import
  118
+  anything inside it (e.g. ``import mysite.settings``).
107 119
 
108  
-    * :file:`settings.py`: Settings/configuration for this Django project.
109  
-      :doc:`/topics/settings` will tell you all about how settings work.
  120
+* :file:`mysite/__init__.py`: An empty file that tells Python that this
  121
+  directory should be considered a Python package. (Read `more about
  122
+  packages`_ in the official Python docs if you're a Python beginner.)
110 123
 
111  
-    * :file:`urls.py`: The URL declarations for this Django project; a "table of
112  
-      contents" of your Django-powered site. You can read more about URLs in
113  
-      :doc:`/topics/http/urls`.
  124
+* :file:`mysite/settings.py`: Settings/configuration for this Django
  125
+  project.  :doc:`/topics/settings` will tell you all about how settings
  126
+  work.
  127
+
  128
+* :file:`mysite/urls.py`: The URL declarations for this Django project; a
  129
+  "table of contents" of your Django-powered site. You can read more about
  130
+  URLs in :doc:`/topics/http/urls`.
114 131
 
115 132
 .. _more about packages: http://docs.python.org/tutorial/modules.html#packages
116 133
 
117 134
 The development server
118 135
 ----------------------
119 136
 
120  
-Let's verify this worked. Change into the :file:`mysite` directory, if you
121  
-haven't already, and run the command ``python manage.py runserver``. You'll see
122  
-the following output on the command line::
  137
+Let's verify this worked. Change into the outer :file:`mysite` directory, if
  138
+you haven't already, and run the command ``python manage.py runserver``. You'll
  139
+see the following output on the command line::
123 140
 
124 141
     Validating models...
125 142
     0 errors found.
126 143
 
127  
-    Django version 1.0, using settings 'mysite.settings'
  144
+    Django version 1.4, using settings 'mysite.settings'
128 145
     Development server is running at http://127.0.0.1:8000/
129 146
     Quit the server with CONTROL-C.
130 147
 
@@ -168,7 +185,7 @@ It worked!
168 185
 Database setup
169 186
 --------------
170 187
 
171  
-Now, edit :file:`settings.py`. It's a normal Python module with
  188
+Now, edit :file:`mysite/settings.py`. It's a normal Python module with
172 189
 module-level variables representing Django settings. Change the
173 190
 following keys in the :setting:`DATABASES` ``'default'`` item to match
174 191
 your databases connection settings.
@@ -286,10 +303,11 @@ so you can focus on writing code rather than creating directories.
286 303
     multiple apps. An app can be in multiple projects.
287 304
 
288 305
 Your apps can live anywhere on your `Python path`_. In this tutorial, we'll
289  
-create our poll app in the :file:`mysite` directory for simplicity.
  306
+create our poll app right next to your :file:`manage.py` file so that it can be
  307
+imported as its own top-level module, rather than a submodule of ``mysite``.
290 308
 
291  
-To create your app, make sure you're in the :file:`mysite` directory and type
292  
-this command:
  309
+To create your app, make sure you're in the same directory as :file:`manage.py`
  310
+and type this command:
293 311
 
294 312
 .. code-block:: bash
295 313
 
@@ -499,27 +517,16 @@ API Django gives you. To invoke the Python shell, use this command:
499 517
 
500 518
     python manage.py shell
501 519
 
502  
-We're using this instead of simply typing "python", because ``manage.py`` sets
503  
-up the project's environment for you. "Setting up the environment" involves two
504  
-things:
505  
-
506  
-    * Putting ``polls`` on ``sys.path``. For flexibility, several pieces of
507  
-      Django refer to projects in Python dotted-path notation (e.g.
508  
-      ``'polls.models'``). In order for this to work, the ``polls``
509  
-      package has to be on ``sys.path``.
510  
-
511  
-      We've already seen one example of this: the :setting:`INSTALLED_APPS`
512  
-      setting is a list of packages in dotted-path notation.
513  
-
514  
-    * Setting the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives
515  
-      Django the path to your ``settings.py`` file.
  520
+We're using this instead of simply typing "python", because :file:`manage.py`
  521
+sets the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives Django
  522
+the Python import path to your :file:`settings.py` file.
516 523
 
517 524
 .. admonition:: Bypassing manage.py
518 525
 
519  
-    If you'd rather not use ``manage.py``, no problem. Just make sure ``mysite``
520  
-    and ``polls`` are at the root level on the Python path (i.e., ``import mysite``
521  
-    and ``import polls`` work) and set the ``DJANGO_SETTINGS_MODULE`` environment
522  
-    variable to ``mysite.settings``.
  526
+    If you'd rather not use :file:`manage.py`, no problem. Just set the
  527
+    ``DJANGO_SETTINGS_MODULE`` environment variable to ``mysite.settings`` and
  528
+    run ``python`` from the same directory :file:`manage.py` is in (or ensure
  529
+    that directory is on the Python path, so that ``import mysite`` works).
523 530
 
524 531
     For more information on all of this, see the :doc:`django-admin.py
525 532
     documentation </ref/django-admin>`.
6  docs/ref/django-admin.txt
@@ -907,12 +907,6 @@ startproject <projectname>
907 907
 Creates a Django project directory structure for the given project name in the
908 908
 current directory.
909 909
 
910  
-This command is disabled when the ``--settings`` option to
911  
-``django-admin.py`` is used, or when the environment variable
912  
-``DJANGO_SETTINGS_MODULE`` has been set. To re-enable it in these
913  
-situations, either omit the ``--settings`` option or unset
914  
-``DJANGO_SETTINGS_MODULE``.
915  
-
916 910
 syncdb
917 911
 ------
918 912
 
90  docs/releases/1.4.txt
@@ -328,6 +328,73 @@ a :class:`~django.forms.fields.GenericIPAddressField` form field and
328 328
 the validators :data:`~django.core.validators.validate_ipv46_address` and
329 329
 :data:`~django.core.validators.validate_ipv6_address`
330 330
 
  331
+Updated default project layout and ``manage.py``
  332
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  333
+
  334
+Django 1.4 ships with an updated default project layout and ``manage.py`` file
  335
+for the :djadmin:`startproject` management command. These fix some issues with
  336
+the previous ``manage.py`` handling of Python import paths that caused double
  337
+imports, trouble moving from development to deployment, and other
  338
+difficult-to-debug path issues.
  339
+
  340
+The previous ``manage.py`` calls functions that are now deprecated, and thus
  341
+projects upgrading to Django 1.4 should update their ``manage.py``. (The
  342
+old-style ``manage.py`` will continue to work as before until Django 1.6; in
  343
+1.5 it will raise ``DeprecationWarning``).
  344
+
  345
+The new recommended ``manage.py`` file should look like this::
  346
+
  347
+    #!/usr/bin/env python
  348
+    import os, sys
  349
+
  350
+    if __name__ == "__main__":
  351
+        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
  352
+
  353
+        from django.core.management import execute_from_command_line
  354
+
  355
+        execute_from_command_line(sys.argv)
  356
+
  357
+``{{ project_name }}`` should be replaced with the Python package name of the
  358
+actual project.
  359
+
  360
+If settings, URLconf, and apps within the project are imported or referenced
  361
+using the project-name prefix (e.g. ``myproject.settings``, ``ROOT_URLCONF =
  362
+``myproject.urls``, etc), the new ``manage.py`` will need to be moved one
  363
+directory up, so it is outside the project package rather than adjacent to
  364
+``settings.py`` and ``urls.py``.
  365
+
  366
+For instance, with the following layout::
  367
+
  368
+    manage.py
  369
+    mysite/
  370
+        __init__.py
  371
+        settings.py
  372
+        urls.py
  373
+        myapp/
  374
+            __init__.py
  375
+            models.py
  376
+
  377
+You could import ``mysite.settings``, ``mysite.urls``, and ``mysite.myapp``,
  378
+but not ``settings``, ``urls``, or ``myapp`` as top-level modules.
  379
+
  380
+Anything imported as a top-level module can be placed adjacent to the new
  381
+``manage.py``. For instance, to decouple "myapp" from the project module and
  382
+import it as just ``myapp``, place it outside the ``mysite/`` directory::
  383
+
  384
+    manage.py
  385
+    myapp/
  386
+        __init__.py
  387
+        models.py
  388
+    mysite/
  389
+        __init__.py
  390
+        settings.py
  391
+        urls.py
  392
+
  393
+If the same code is imported inconsistently (some places with the project
  394
+prefix, some places without it), the imports will need to be cleaned up when
  395
+switching to the new ``manage.py``.
  396
+
  397
+
331 398
 Minor features
332 399
 ~~~~~~~~~~~~~~
333 400
 
@@ -729,3 +796,26 @@ The code that powers Databrowse is licensed under the same terms as Django
729 796
 itself, and so is available to be adopted by an individual or group as
730 797
 a third-party project.
731 798
 
  799
+``django.core.management.setup_environ``
  800
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  801
+
  802
+This function temporarily modified ``sys.path`` in order to make the parent
  803
+"project" directory importable under the old flat :djadmin:`startproject`
  804
+layout. This function is now deprecated, as its path workarounds are no longer
  805
+needed with the new ``manage.py`` and default project layout.
  806
+
  807
+This function was never documented or public API, but was widely recommended
  808
+for use in setting up a "Django environment" for a user script. These uses
  809
+should be replaced by setting the ``DJANGO_SETTINGS_MODULE`` environment
  810
+variable or using :func:`django.conf.settings.configure`.
  811
+
  812
+``django.core.management.execute_manager``
  813
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  814
+
  815
+This function was previously used by ``manage.py`` to execute a management
  816
+command. It is identical to
  817
+``django.core.management.execute_from_command_line``, except that it first
  818
+calls ``setup_environ``, which is now deprecated. ``execute_manager`` is also
  819
+deprecated; ``execute_from_command_line`` can be used instead. (Neither of
  820
+these functions is documented public API, but a deprecation path is needed due
  821
+to use in existing ``manage.py`` files.)
129  tests/regressiontests/admin_scripts/tests.py
@@ -3,6 +3,8 @@
3 3
 advertised - especially with regards to the handling of the DJANGO_SETTINGS_MODULE
4 4
 and default settings.py files.
5 5
 """
  6
+from __future__ import with_statement
  7
+
6 8
 import os
7 9
 import shutil
8 10
 import sys
@@ -35,7 +37,7 @@ def write_settings(self, filename, apps=None, is_dir=False, sdict=None):
35 37
                 settings_file.write("%s = %s\n" % (s, o))
36 38
 
37 39
         if apps is None:
38  
-            apps = ['django.contrib.auth', 'django.contrib.contenttypes', 'admin_scripts']
  40
+            apps = ['django.contrib.auth', 'django.contrib.contenttypes', 'regressiontests.admin_scripts']
39 41
 
40 42
         settings_file.write("INSTALLED_APPS = %s\n" % apps)
41 43
 
@@ -100,7 +102,7 @@ def run_test(self, script, args, settings_file=None, apps=None):
100 102
             os.environ['DJANGO_SETTINGS_MODULE'] = settings_file
101 103
         elif 'DJANGO_SETTINGS_MODULE' in os.environ:
102 104
             del os.environ['DJANGO_SETTINGS_MODULE']
103  
-        python_path = [test_dir, base_dir]
  105
+        python_path = [project_dir, base_dir]
104 106
         python_path.extend(ext_backend_base_dirs)
105 107
         os.environ[python_path_var_name] = os.pathsep.join(python_path)
106 108
 
@@ -148,6 +150,13 @@ def run_manage(self, args, settings_file=None):
148 150
         test_manage_py = os.path.join(test_dir, 'manage.py')
149 151
         shutil.copyfile(template_manage_py, test_manage_py)
150 152
 
  153
+        with open(test_manage_py, 'r') as fp:
  154
+            manage_py_contents = fp.read()
  155
+        manage_py_contents = manage_py_contents.replace(
  156
+            "{{ project_name }}", "regressiontests")
  157
+        with open(test_manage_py, 'w') as fp:
  158
+            fp.write(manage_py_contents)
  159
+
151 160
         stdout, stderr = self.run_test('./manage.py', args, settings_file)
152 161
 
153 162
         # Cleanup - remove the generated manage.py script
@@ -224,7 +233,7 @@ def test_builtin_command(self):
224 233
 
225 234
     def test_builtin_with_settings(self):
226 235
         "default: django-admin builtin commands succeed if settings are provided as argument"
227  
-        args = ['sqlall','--settings=settings', 'admin_scripts']
  236
+        args = ['sqlall','--settings=regressiontests.settings', 'admin_scripts']
228 237
         out, err = self.run_django_admin(args)
229 238
         self.assertNoOutput(err)
230 239
         self.assertOutput(out, 'CREATE TABLE')
@@ -232,7 +241,7 @@ def test_builtin_with_settings(self):
232 241
     def test_builtin_with_environment(self):
233 242
         "default: django-admin builtin commands succeed if settings are provided in the environment"
234 243
         args = ['sqlall','admin_scripts']
235  
-        out, err = self.run_django_admin(args,'settings')
  244
+        out, err = self.run_django_admin(args,'regressiontests.settings')
236 245
         self.assertNoOutput(err)
237 246
         self.assertOutput(out, 'CREATE TABLE')
238 247
 
@@ -259,7 +268,7 @@ def test_custom_command(self):
259 268
 
260 269
     def test_custom_command_with_settings(self):
261 270
         "default: django-admin can execute user commands if settings are provided as argument"
262  
-        args = ['noargs_command', '--settings=settings']
  271
+        args = ['noargs_command', '--settings=regressiontests.settings']
263 272
         out, err = self.run_django_admin(args)
264 273
         self.assertNoOutput(err)
265 274
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
@@ -267,7 +276,7 @@ def test_custom_command_with_settings(self):
267 276
     def test_custom_command_with_environment(self):
268 277
         "default: django-admin can execute user commands if settings are provided in environment"
269 278
         args = ['noargs_command']
270  
-        out, err = self.run_django_admin(args,'settings')
  279
+        out, err = self.run_django_admin(args,'regressiontests.settings')
271 280
         self.assertNoOutput(err)
272 281
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
273 282
 
@@ -290,7 +299,7 @@ def test_builtin_command(self):
290 299
 
291 300
     def test_builtin_with_settings(self):
292 301
         "fulldefault: django-admin builtin commands succeed if a settings file is provided"
293  
-        args = ['sqlall','--settings=settings', 'admin_scripts']
  302
+        args = ['sqlall','--settings=regressiontests.settings', 'admin_scripts']
294 303
         out, err = self.run_django_admin(args)
295 304
         self.assertNoOutput(err)
296 305
         self.assertOutput(out, 'CREATE TABLE')
@@ -298,7 +307,7 @@ def test_builtin_with_settings(self):
298 307
     def test_builtin_with_environment(self):
299 308
         "fulldefault: django-admin builtin commands succeed if the environment contains settings"
300 309
         args = ['sqlall','admin_scripts']
301  
-        out, err = self.run_django_admin(args,'settings')
  310
+        out, err = self.run_django_admin(args,'regressiontests.settings')
302 311
         self.assertNoOutput(err)
303 312
         self.assertOutput(out, 'CREATE TABLE')
304 313
 
@@ -325,7 +334,7 @@ def test_custom_command(self):
325 334
 
326 335
     def test_custom_command_with_settings(self):
327 336
         "fulldefault: django-admin can execute user commands if settings are provided as argument"
328  
-        args = ['noargs_command', '--settings=settings']
  337
+        args = ['noargs_command', '--settings=regressiontests.settings']
329 338
         out, err = self.run_django_admin(args)
330 339
         self.assertNoOutput(err)
331 340
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
@@ -333,7 +342,7 @@ def test_custom_command_with_settings(self):
333 342
     def test_custom_command_with_environment(self):
334 343
         "fulldefault: django-admin can execute user commands if settings are provided in environment"
335 344
         args = ['noargs_command']
336  
-        out, err = self.run_django_admin(args,'settings')
  345
+        out, err = self.run_django_admin(args,'regressiontests.settings')
337 346
         self.assertNoOutput(err)
338 347
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
339 348
 
@@ -356,7 +365,7 @@ def test_builtin_command(self):
356 365
 
357 366
     def test_builtin_with_settings(self):
358 367
         "minimal: django-admin builtin commands fail if settings are provided as argument"
359  
-        args = ['sqlall','--settings=settings', 'admin_scripts']
  368
+        args = ['sqlall','--settings=regressiontests.settings', 'admin_scripts']
360 369
         out, err = self.run_django_admin(args)
361 370
         self.assertNoOutput(out)
362 371
         self.assertOutput(err, 'App with label admin_scripts could not be found')
@@ -364,7 +373,7 @@ def test_builtin_with_settings(self):
364 373
     def test_builtin_with_environment(self):
365 374
         "minimal: django-admin builtin commands fail if settings are provided in the environment"
366 375
         args = ['sqlall','admin_scripts']
367  
-        out, err = self.run_django_admin(args,'settings')
  376
+        out, err = self.run_django_admin(args,'regressiontests.settings')
368 377
         self.assertNoOutput(out)
369 378
         self.assertOutput(err, 'App with label admin_scripts could not be found')
370 379
 
@@ -391,7 +400,7 @@ def test_custom_command(self):
391 400
 
392 401
     def test_custom_command_with_settings(self):
393 402
         "minimal: django-admin can't execute user commands, even if settings are provided as argument"
394  
-        args = ['noargs_command', '--settings=settings']
  403
+        args = ['noargs_command', '--settings=regressiontests.settings']
395 404
         out, err = self.run_django_admin(args)
396 405
         self.assertNoOutput(out)
397 406
         self.assertOutput(err, "Unknown command: 'noargs_command'")
@@ -399,7 +408,7 @@ def test_custom_command_with_settings(self):
399 408
     def test_custom_command_with_environment(self):
400 409
         "minimal: django-admin can't execute user commands, even if settings are provided in environment"
401 410
         args = ['noargs_command']
402  
-        out, err = self.run_django_admin(args,'settings')
  411
+        out, err = self.run_django_admin(args,'regressiontests.settings')
403 412
         self.assertNoOutput(out)
404 413
         self.assertOutput(err, "Unknown command: 'noargs_command'")
405 414
 
@@ -422,7 +431,7 @@ def test_builtin_command(self):
422 431
 
423 432
     def test_builtin_with_settings(self):
424 433
         "alternate: django-admin builtin commands succeed if settings are provided as argument"
425  
-        args = ['sqlall','--settings=alternate_settings', 'admin_scripts']
  434
+        args = ['sqlall','--settings=regressiontests.alternate_settings', 'admin_scripts']
426 435
         out, err = self.run_django_admin(args)
427 436
         self.assertNoOutput(err)
428 437
         self.assertOutput(out, 'CREATE TABLE')
@@ -430,7 +439,7 @@ def test_builtin_with_settings(self):
430 439
     def test_builtin_with_environment(self):
431 440
         "alternate: django-admin builtin commands succeed if settings are provided in the environment"
432 441
         args = ['sqlall','admin_scripts']
433  
-        out, err = self.run_django_admin(args,'alternate_settings')
  442
+        out, err = self.run_django_admin(args,'regressiontests.alternate_settings')
434 443
         self.assertNoOutput(err)
435 444
         self.assertOutput(out, 'CREATE TABLE')
436 445
 
@@ -457,7 +466,7 @@ def test_custom_command(self):
457 466
 
458 467
     def test_custom_command_with_settings(self):
459 468
         "alternate: django-admin can execute user commands if settings are provided as argument"
460  
-        args = ['noargs_command', '--settings=alternate_settings']
  469
+        args = ['noargs_command', '--settings=regressiontests.alternate_settings']
461 470
         out, err = self.run_django_admin(args)
462 471
         self.assertNoOutput(err)
463 472
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
@@ -465,7 +474,7 @@ def test_custom_command_with_settings(self):
465 474
     def test_custom_command_with_environment(self):
466 475
         "alternate: django-admin can execute user commands if settings are provided in environment"
467 476
         args = ['noargs_command']
468  
-        out, err = self.run_django_admin(args,'alternate_settings')
  477
+        out, err = self.run_django_admin(args,'regressiontests.alternate_settings')
469 478
         self.assertNoOutput(err)
470 479
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
471 480
 
@@ -493,7 +502,7 @@ def test_builtin_command(self):
493 502
 
494 503
     def test_builtin_with_settings(self):
495 504
         "alternate: django-admin builtin commands succeed if settings are provided as argument"
496  
-        args = ['sqlall','--settings=alternate_settings', 'admin_scripts']
  505
+        args = ['sqlall','--settings=regressiontests.alternate_settings', 'admin_scripts']
497 506
         out, err = self.run_django_admin(args)
498 507
         self.assertNoOutput(err)
499 508
         self.assertOutput(out, 'CREATE TABLE')
@@ -501,7 +510,7 @@ def test_builtin_with_settings(self):
501 510
     def test_builtin_with_environment(self):
502 511
         "alternate: django-admin builtin commands succeed if settings are provided in the environment"
503 512
         args = ['sqlall','admin_scripts']
504  
-        out, err = self.run_django_admin(args,'alternate_settings')
  513
+        out, err = self.run_django_admin(args,'regressiontests.alternate_settings')
505 514
         self.assertNoOutput(err)
506 515
         self.assertOutput(out, 'CREATE TABLE')
507 516
 
@@ -526,16 +535,16 @@ def test_custom_command(self):
526 535
         self.assertOutput(err, "Unknown command: 'noargs_command'")
527 536
 
528 537
     def test_custom_command_with_settings(self):
529  
-        "alternate: django-admin can't execute user commands, even if settings are provided as argument"
530  
-        args = ['noargs_command', '--settings=alternate_settings']
  538
+        "alternate: django-admin can execute user commands if settings are provided as argument"
  539
+        args = ['noargs_command', '--settings=regressiontests.alternate_settings']
531 540
         out, err = self.run_django_admin(args)
532 541
         self.assertNoOutput(err)
533 542
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
534 543
 
535 544
     def test_custom_command_with_environment(self):
536  
-        "alternate: django-admin can't execute user commands, even if settings are provided in environment"
  545
+        "alternate: django-admin can execute user commands if settings are provided in environment"
537 546
         args = ['noargs_command']
538  
-        out, err = self.run_django_admin(args,'alternate_settings')
  547
+        out, err = self.run_django_admin(args,'regressiontests.alternate_settings')
539 548
         self.assertNoOutput(err)
540 549
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
541 550
 
@@ -557,7 +566,7 @@ def test_setup_environ(self):
557 566
         test_dir = os.path.dirname(os.path.dirname(__file__))
558 567
         args = ['startapp','settings_test']
559 568
         app_path = os.path.join(test_dir, 'settings_test')
560  
-        out, err = self.run_django_admin(args,'settings')
  569
+        out, err = self.run_django_admin(args,'regressiontests.settings')
561 570
         self.addCleanup(shutil.rmtree, app_path)
562 571
         self.assertNoOutput(err)
563 572
         self.assertTrue(os.path.exists(app_path))
@@ -591,7 +600,7 @@ def test_custom_command(self):
591 600
 
592 601
     def test_builtin_with_settings(self):
593 602
         "directory: django-admin builtin commands succeed if settings are provided as argument"
594  
-        args = ['sqlall','--settings=settings', 'admin_scripts']
  603
+        args = ['sqlall','--settings=regressiontests.settings', 'admin_scripts']
595 604
         out, err = self.run_django_admin(args)
596 605
         self.assertNoOutput(err)
597 606
         self.assertOutput(out, 'CREATE TABLE')
@@ -599,7 +608,7 @@ def test_builtin_with_settings(self):
599 608
     def test_builtin_with_environment(self):
600 609
         "directory: django-admin builtin commands succeed if settings are provided in the environment"
601 610
         args = ['sqlall','admin_scripts']
602  
-        out, err = self.run_django_admin(args,'settings')
  611
+        out, err = self.run_django_admin(args,'regressiontests.settings')
603 612
         self.assertNoOutput(err)
604 613
         self.assertOutput(out, 'CREATE TABLE')
605 614
 
@@ -618,21 +627,21 @@ def test_builtin_command(self):
618 627
         args = ['sqlall','admin_scripts']
619 628
         out, err = self.run_manage(args)
620 629
         self.assertNoOutput(out)
621  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  630
+        self.assertOutput(err, "Could not import settings 'regressiontests.settings'")
622 631
 
623 632
     def test_builtin_with_bad_settings(self):
624 633
         "no settings: manage.py builtin commands fail if settings file (from argument) doesn't exist"
625 634
         args = ['sqlall','--settings=bad_settings', 'admin_scripts']
626 635
         out, err = self.run_manage(args)
627 636
         self.assertNoOutput(out)
628  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  637
+        self.assertOutput(err, "Could not import settings 'bad_settings'")
629 638
 
630 639
     def test_builtin_with_bad_environment(self):
631 640
         "no settings: manage.py builtin commands fail if settings file (from environment) doesn't exist"
632 641
         args = ['sqlall','admin_scripts']
633 642
         out, err = self.run_manage(args,'bad_settings')
634 643
         self.assertNoOutput(out)
635  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  644
+        self.assertOutput(err, "Could not import settings 'bad_settings'")
636 645
 
637 646
 
638 647
 class ManageDefaultSettings(AdminScriptTestCase):
@@ -654,7 +663,7 @@ def test_builtin_command(self):
654 663
 
655 664
     def test_builtin_with_settings(self):
656 665
         "default: manage.py builtin commands succeed if settings are provided as argument"
657  
-        args = ['sqlall','--settings=settings', 'admin_scripts']
  666
+        args = ['sqlall','--settings=regressiontests.settings', 'admin_scripts']
658 667
         out, err = self.run_manage(args)
659 668
         self.assertNoOutput(err)
660 669
         self.assertOutput(out, 'CREATE TABLE')
@@ -662,7 +671,7 @@ def test_builtin_with_settings(self):
662 671
     def test_builtin_with_environment(self):
663 672
         "default: manage.py builtin commands succeed if settings are provided in the environment"
664 673
         args = ['sqlall','admin_scripts']
665  
-        out, err = self.run_manage(args,'settings')
  674
+        out, err = self.run_manage(args,'regressiontests.settings')
666 675
         self.assertNoOutput(err)
667 676
         self.assertOutput(out, 'CREATE TABLE')
668 677
 
@@ -689,7 +698,7 @@ def test_custom_command(self):
689 698
 
690 699
     def test_custom_command_with_settings(self):
691 700
         "default: manage.py can execute user commands when settings are provided as argument"
692  
-        args = ['noargs_command', '--settings=settings']
  701
+        args = ['noargs_command', '--settings=regressiontests.settings']
693 702
         out, err = self.run_manage(args)
694 703
         self.assertNoOutput(err)
695 704
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
@@ -697,7 +706,7 @@ def test_custom_command_with_settings(self):
697 706
     def test_custom_command_with_environment(self):
698 707
         "default: manage.py can execute user commands when settings are provided in environment"
699 708
         args = ['noargs_command']
700  
-        out, err = self.run_manage(args,'settings')
  709
+        out, err = self.run_manage(args,'regressiontests.settings')
701 710
         self.assertNoOutput(err)
702 711
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
703 712
 
@@ -721,7 +730,7 @@ def test_builtin_command(self):
721 730
 
722 731
     def test_builtin_with_settings(self):
723 732
         "fulldefault: manage.py builtin commands succeed if settings are provided as argument"
724  
-        args = ['sqlall','--settings=settings', 'admin_scripts']
  733
+        args = ['sqlall','--settings=regressiontests.settings', 'admin_scripts']
725 734
         out, err = self.run_manage(args)
726 735
         self.assertNoOutput(err)
727 736
         self.assertOutput(out, 'CREATE TABLE')
@@ -729,7 +738,7 @@ def test_builtin_with_settings(self):
729 738
     def test_builtin_with_environment(self):
730 739
         "fulldefault: manage.py builtin commands succeed if settings are provided in the environment"
731 740
         args = ['sqlall','admin_scripts']
732  
-        out, err = self.run_manage(args,'settings')
  741
+        out, err = self.run_manage(args,'regressiontests.settings')
733 742
         self.assertNoOutput(err)
734 743
         self.assertOutput(out, 'CREATE TABLE')
735 744
 
@@ -756,7 +765,7 @@ def test_custom_command(self):
756 765
 
757 766
     def test_custom_command_with_settings(self):
758 767
         "fulldefault: manage.py can execute user commands when settings are provided as argument"
759  
-        args = ['noargs_command', '--settings=settings']
  768
+        args = ['noargs_command', '--settings=regressiontests.settings']
760 769
         out, err = self.run_manage(args)
761 770
         self.assertNoOutput(err)
762 771
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
@@ -764,7 +773,7 @@ def test_custom_command_with_settings(self):
764 773
     def test_custom_command_with_environment(self):
765 774
         "fulldefault: manage.py can execute user commands when settings are provided in environment"
766 775
         args = ['noargs_command']
767  
-        out, err = self.run_manage(args,'settings')
  776
+        out, err = self.run_manage(args,'regressiontests.settings')
768 777
         self.assertNoOutput(err)
769 778
         self.assertOutput(out, "EXECUTE:NoArgsCommand")
770 779
 
@@ -787,7 +796,7 @@ def test_builtin_command(self):
787 796
 
788 797
     def test_builtin_with_settings(self):
789 798
         "minimal: manage.py builtin commands fail if settings are provided as argument"
790  
-        args = ['sqlall','--settings=settings', 'admin_scripts']
  799
+        args = ['sqlall','--settings=regressiontests.settings', 'admin_scripts']
791 800
         out, err = self.run_manage(args)
792 801
         self.assertNoOutput(out)
793 802
         self.assertOutput(err, 'App with label admin_scripts could not be found')
@@ -795,7 +804,7 @@ def test_builtin_with_settings(self):
795 804
     def test_builtin_with_environment(self):
796 805
         "minimal: manage.py builtin commands fail if settings are provided in the environment"
797 806
         args = ['sqlall','admin_scripts']
798  
-        out, err = self.run_manage(args,'settings')
  807
+        out, err = self.run_manage(args,'regressiontests.settings')
799 808
         self.assertNoOutput(out)
800 809
         self.assertOutput(err, 'App with label admin_scripts could not be found')
801 810
 
@@ -822,7 +831,7 @@ def test_custom_command(self):
822 831
 
823 832
     def test_custom_command_with_settings(self):
824 833
         "minimal: manage.py can't execute user commands, even if settings are provided as argument"
825  
-        args = ['noargs_command', '--settings=settings']
  834
+        args = ['noargs_command', '--settings=regressiontests.settings']
826 835
         out, err = self.run_manage(args)
827 836
         self.assertNoOutput(out)
828 837
         self.assertOutput(err, "Unknown command: 'noargs_command'")
@@ -830,7 +839,7 @@ def test_custom_command_with_settings(self):
830 839
     def test_custom_command_with_environment(self):
831 840
         "minimal: manage.py can't execute user commands, even if settings are provided in environment"
832 841
         args = ['noargs_command']
833  
-        out, err = self.run_manage(args,'settings')
  842
+        out, err = self.run_manage(args,'regressiontests.settings')
834 843
         self.assertNoOutput(out)
835 844
         self.assertOutput(err, "Unknown command: 'noargs_command'")
836 845
 
@@ -849,56 +858,56 @@ def test_builtin_command(self):
849 858
         args = ['sqlall','admin_scripts']
850 859
         out, err = self.run_manage(args)
851 860
         self.assertNoOutput(out)
852  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  861
+        self.assertOutput(err, "Could not import settings 'regressiontests.settings'")
853 862
 
854 863
     def test_builtin_with_settings(self):
855  
-        "alternate: manage.py builtin commands fail if settings are provided as argument but no defaults"
  864
+        "alternate: manage.py builtin commands work with settings provided as argument"
856 865
         args = ['sqlall','--settings=alternate_settings', 'admin_scripts']
857 866
         out, err = self.run_manage(args)
858  
-        self.assertNoOutput(out)
859  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  867
+        self.assertOutput(out, 'CREATE TABLE "admin_scripts_article"')
  868
+        self.assertNoOutput(err)
860 869
 
861 870
     def test_builtin_with_environment(self):
862  
-        "alternate: manage.py builtin commands fail if settings are provided in the environment but no defaults"
  871
+        "alternate: manage.py builtin commands work if settings are provided in the environment"
863 872
         args = ['sqlall','admin_scripts']
864 873
         out, err = self.run_manage(args,'alternate_settings')
865  
-        self.assertNoOutput(out)
866  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  874
+        self.assertOutput(out, 'CREATE TABLE "admin_scripts_article"')
  875
+        self.assertNoOutput(err)
867 876
 
868 877
     def test_builtin_with_bad_settings(self):
869 878
         "alternate: manage.py builtin commands fail if settings file (from argument) doesn't exist"
870 879
         args = ['sqlall','--settings=bad_settings', 'admin_scripts']
871 880
         out, err = self.run_manage(args)
872 881
         self.assertNoOutput(out)
873  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  882
+        self.assertOutput(err, "Could not import settings 'bad_settings'")
874 883
 
875 884
     def test_builtin_with_bad_environment(self):
876 885
         "alternate: manage.py builtin commands fail if settings file (from environment) doesn't exist"
877 886
         args = ['sqlall','admin_scripts']
878 887
         out, err = self.run_manage(args,'bad_settings')
879 888
         self.assertNoOutput(out)
880  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  889
+        self.assertOutput(err, "Could not import settings 'bad_settings'")
881 890
 
882 891
     def test_custom_command(self):
883  
-        "alternate: manage.py can't execute user commands"
  892
+        "alternate: manage.py can't execute user commands without settings"
884 893
         args = ['noargs_command']
885 894
         out, err = self.run_manage(args)
886 895
         self.assertNoOutput(out)
887  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  896
+        self.assertOutput(err, "Unknown command: 'noargs_command'")
888 897
 
889 898
     def test_custom_command_with_settings(self):
890  
-        "alternate: manage.py can't execute user commands, even if settings are provided as argument"
  899
+        "alternate: manage.py can execute user commands if settings are provided as argument"
891 900
         args = ['noargs_command', '--settings=alternate_settings']
892 901
         out, err = self.run_manage(args)
893  
-        self.assertNoOutput(out)
894  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  902
+        self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]")
  903
+        self.assertNoOutput(err)
895 904
 
896 905
     def test_custom_command_with_environment(self):
897  
-        "alternate: manage.py can't execute user commands, even if settings are provided in environment"
  906
+        "alternate: manage.py can execute user commands if settings are provided in environment"
898 907
         args = ['noargs_command']
899 908
         out, err = self.run_manage(args,'alternate_settings')
900  
-        self.assertNoOutput(out)
901  
-        self.assertOutput(err, "Can't find the file 'settings.py' in the directory containing './manage.py'")
  909
+        self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]")
  910
+        self.assertNoOutput(err)
902 911
 
903 912
 
904 913
 class ManageMultipleSettings(AdminScriptTestCase):
@@ -999,7 +1008,7 @@ def test_builtin_command(self):
999 1008
         args = ['sqlall','admin_scripts']
1000 1009
         out, err = self.run_manage(args)
1001 1010
         self.assertNoOutput(out)
1002  
-        self.assertOutput(err, "ImportError: No module named foo42bar")
  1011
+        self.assertOutput(err, "No module named foo42bar")
1003 1012
 
1004 1013
 class ManageValidate(AdminScriptTestCase):
1005 1014
     def tearDown(self):
8  tests/regressiontests/test_runner/tests.py
@@ -188,25 +188,25 @@ def tearDown(self):
188 188
         self.remove_settings('settings.py')
189 189
 
190 190
     def test_default_options(self):
191  
-        args = ['test', '--settings=settings']
  191
+        args = ['test', '--settings=regressiontests.settings']
192 192
         out, err = self.run_django_admin(args)
193 193
         self.assertNoOutput(err)
194 194
         self.assertOutput(out, '1:2:3')
195 195
 
196 196
     def test_default_and_given_options(self):
197  
-        args = ['test', '--settings=settings', '--option_b=foo']
  197
+        args = ['test', '--settings=regressiontests.settings', '--option_b=foo']
198 198
         out, err = self.run_django_admin(args)
199 199
         self.assertNoOutput(err)
200 200
         self.assertOutput(out, '1:foo:3')
201 201
 
202 202
     def test_option_name_and_value_separated(self):
203  
-        args = ['test', '--settings=settings', '--option_b', 'foo']
  203
+        args = ['test', '--settings=regressiontests.settings', '--option_b', 'foo']
204 204
         out, err = self.run_django_admin(args)
205 205
         self.assertNoOutput(err)
206 206
         self.assertOutput(out, '1:foo:3')
207 207
 
208 208
     def test_all_options_given(self):
209  
-        args = ['test', '--settings=settings', '--option_a=bar', '--option_b=foo', '--option_c=31337']
  209
+        args = ['test', '--settings=regressiontests.settings', '--option_a=bar', '--option_b=foo', '--option_c=31337']
210 210
         out, err = self.run_django_admin(args)
211 211
         self.assertNoOutput(err)
212 212
         self.assertOutput(out, 'bar:foo:31337')

0 notes on commit 38f1fe3

James Pic

Before, we could run scripts outside django, by just doing "import manage" at the top. Now it's not possible anymore because the django project is setup only if name == 'main'. Is it normal ? Wasn't it cool to just do "import manage" and then be able to use the django project in a script ?

Carl Meyer

manage.py is intended for use as a command-line script. It's bad behavior for a script to make modifications to the environment as a side-effect of import (explicit is better than implicit). Plus, the big advantage of this commit is that there is no longer any such thing as "setting up the Django project", it's nothing more than making sure DJANGO_SETTINGS_MODULE is set, which is a one-liner anyway in a script, so I can't see much advantage in doing it by importing manage.py.

In any case, if you disagree and want to do it that way, you're free to change manage.py in your projects so it sets DJANGO_SETTINGS_MODULE any time it's imported.

James Pic

Fantastic, great answer, thanks a heap !

Please sign in to comment.
Something went wrong with that request. Please try again.