0

This is what the structure of my project is. This question will ignore the 'lib' directory:

project
    app
        data -> migrations, models, __init__.py
        prodsite -> settings.py, urls.py, wsgi.py, __init__.py
        testsite -> same as above
    lib
        data -> migrations, models, __init__.py
        prodsite -> settings.py, urls.py, wsgi.py, __init__.py, common models
        testsite -> same as above
    tools
        manage.py

I want to be able to run:

python tools/manage.py app.prodsite (makemigrations/migrate) app

It was not hard to modify manage.py so that it adds the root directory to the system path, sets the django environment variable to 'app.prodsite', and deletes that argument from sys.argv, before continuing on with what manage.py normally does. I could not manage to get rid of the last parameter without causing errors:

#!/usr/bin/env python
import os
import sys
import inspect

def main():
    sys.path.append(os.getcwd()) # allow reative to cwd, not just module.py.
    if "DJANGO_SETTINGS_MODULE" not in os.environ:
        if len(sys.argv) < 3:
            print("Error in command: {}".format(" ".join(sys.argv)))
            print("manage.py should be called like:\r\n"
                  "manage.py <app> <operation>.")
            return
        os.environ.setdefault("DJANGO_SETTINGS_MODULE",
                              "{}.settings".format(sys.argv[1]))
        del sys.argv[1]
    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
    execute_from_command_line(sys.argv)

if __name__ == "__main__":
    main()

These are the other relevant files:

# project.app.data:
class M(Model):
    class Meta:
        app_label = 'app.data'
    a: bool
    b: str
    c: float

# project.app.data.apps
class DataConfig(AppConfig):
    name = 'app.data'

# project.app.data.__init__
default_app_config = 'app.data.apps.DataConfig'

# project.app.prodsite.settings
ROOT_URLCONF = 'app.prodsite.urls'
WSGI_APPLICATION = 'app.prodsite.wsgi.application'
INSTALLED_APPS += ['app.data', 'app.micsite']

If I try running 'python bldtool/manage.py app.prodsite makemigrations app.data', I get an error asking if app.data is in INSTALLED_APPS.

No errors are generated if I only include 'app' in INSTALLED_APPS, but then django does not detect any changes and does not generate a migrations directory. (I have tried creating a migrations directory with init.py, with no success, either)

What can I do to make this work as expected?

walrusk
  • 1
  • 2

2 Answers2

2

According to django documentations:

A list of strings designating all applications that are enabled in this Django installation. Each string should be a dotted Python path to:

  • an application configuration class (preferred), or
  • a package containing an application.

Also, migrations directories ( with __init__.py files inside them) should be created before running makemigrations without specifying app name, otherwise, no changes will be detected by makemigrations command. But if you specify app name, makemigrations will work even without migrations directory.

razieh babaee
  • 298
  • 5
  • 19
  • I tried setting the application path to the class, but I still get the same error about the INSTALLED_APPS unless I have the the entire app directory in INSTALLED_APPS (in which case no migrations are detected even with a migrations directory with __init__.py, under the data directory) – walrusk Oct 13 '18 at 11:22
  • What worked was having: INSTALLED_APPS = ['app.data.apps.DataConfig', 'app'] I did not need the app/data/__init__.py nor did I need an empty migrations directory, in order to generate the initial migrations. My only complaint right now is that the migrations folder is under app instead of app/data. I think I can make do with this, but please let me know if you have any ideas that could make this happen. Thanks! – walrusk Oct 14 '18 at 23:48
  • Another thing is that if I delete the migrations directory and try to run makemigrations again, the output stays the same - no changes detected. I tried creating an empty migrations directory with an __init__.py, but that didn't seem to make a difference. – walrusk Oct 14 '18 at 23:58
  • If you specify app name, the migrations directory will not be needed anymore. So, if there are no changes detected, there might be something wrong with your application's path or other settings ... I suggest rechecking all settings in your settings.py file :) also, check the app_label in the meta classes. take a look at https://stackoverflow.com/questions/36153748/django-1-9-makemigrations-no-changes-detected/36154224 – razieh babaee Oct 15 '18 at 11:06
0

The configuration that works for me in this particular case is:

# project.app.data:
class M(Model):
    class Meta:
        app_label = 'data' # Not full path
    a: bool
    b: str
    c: float

# project.app.data.apps
class DataConfig(AppConfig):
    name = 'app.data'

# project.app.data.__init__
# Empty

# project.app.prodsite.settings
ROOT_URLCONF = 'app.prodsite.urls'
WSGI_APPLICATION = 'app.prodsite.wsgi.application'
INSTALLED_APPS += ['app.data', 'app'] # No need for app.micsite

The above (along with the modified manage.py) allows me to perform:

python tools/manage.py app.prodsite [makemigrations|migrate] data
walrusk
  • 1
  • 2