I am using Django 4.0
I have written two standalone apps. Foo
and FooBar
.
Application Foo
uses package django_nyt. Application FooBar
uses functionality from application Foo
.
I am able to makemigrations
and migrate
models in application Foo
, however, when working with application FooBar
, when I attempt to makemigrations
, I get the following error trace:
Traceback (most recent call last):
File "manage.py", line 14, in <module>
execute_from_command_line(sys.argv)
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
utility.execute()
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/core/management/__init__.py", line 440, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/core/management/base.py", line 414, in run_from_argv
self.execute(*args, **cmd_options)
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/core/management/base.py", line 460, in execute
output = self.handle(*args, **options)
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/core/management/base.py", line 98, in wrapped
res = handle_func(*args, **kwargs)
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/core/management/commands/makemigrations.py", line 100, in handle
loader = MigrationLoader(None, ignore_no_migrations=True)
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/db/migrations/loader.py", line 58, in __init__
self.build_graph()
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/db/migrations/loader.py", line 276, in build_graph
self.graph.validate_consistency()
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/db/migrations/graph.py", line 198, in validate_consistency
[n.raise_error() for n in self.node_map.values() if isinstance(n, DummyNode)]
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/db/migrations/graph.py", line 198, in <listcomp>
[n.raise_error() for n in self.node_map.values() if isinstance(n, DummyNode)]
File "/path/to/project/foobar/env/lib/python3.8/site-packages/django/db/migrations/graph.py", line 60, in raise_error
raise NodeNotFoundError(self.error_message, self.key, origin=self.origin)
django.db.migrations.exceptions.NodeNotFoundError: Migration foo.0001_initial dependencies reference nonexistent parent node ('django_nyt', '0010_auto_20220802_2211')
contents of /path/to/proj/foo/env/lib/python3.8/site-packages/django_nyt/migrations/0010_auto_20220802_2211
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('django_nyt', '0009_alter_notification_subscription_and_more'),
]
operations = [
migrations.AlterField(
model_name='notification',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='settings',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='subscription',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
]
Since these are standalone apps, I am using the design pattern advocated for in Django Standalone Reusable Libraries.
common.py (foo application)
from pathlib import Path
from django.conf import settings
SAMPLE_PROJECT_DIR_NAME='sample_project'
BASE_DIR = f"{Path(__file__).parent.resolve()}/{SAMPLE_PROJECT_DIR_NAME}"
STANDALONE_APP_NAME='foo'
STATIC_URL = '/static/'
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.admin',
'django.contrib.messages',
'django.contrib.humanize',
'django.contrib.sites',
'django_nyt.apps.DjangoNytConfig',
STANDALONE_APP_NAME,
'myapp',
]
SECRET_KEY="lskfjklsdfjalkfslfjslfksdjfslkfslkfj"
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
DEBUG=True
# AUTH_USER_MODEL='testdata.CustomUser',
DATABASES={
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': f"{BASE_DIR}/db.sqlite3",
},
}
SITE_ID=1
ROOT_URLCONF=f"{SAMPLE_PROJECT_DIR_NAME}.urls"
TEMPLATES=[
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.messages.context_processors.messages',
]
},
},
]
USE_TZ=True
MIDDLEWARE=[
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
]
settings.configure(
SECRET_KEY=SECRET_KEY,
DEFAULT_AUTO_FIELD = DEFAULT_AUTO_FIELD,
DEBUG=DEBUG,
# AUTH_USER_MODEL=AUTH_USER_MODEL,
DATABASES=DATABASES,
SITE_ID=SITE_ID,
ROOT_URLCONF=ROOT_URLCONF,
INSTALLED_APPS=INSTALLED_APPS,
STATIC_URL=STATIC_URL,
TEMPLATES=TEMPLATES,
USE_TZ=USE_TZ,
MIDDLEWARE=MIDDLEWARE,
)
common.py (foobar)
import sys
from pathlib import Path
from django.conf import settings
SAMPLE_PROJECT_DIR_NAME='sample_project'
PARENT_DIR = f"{Path(__file__).parent.parent.resolve()}"
BASE_DIR = f"{Path(__file__).parent.resolve()}/{SAMPLE_PROJECT_DIR_NAME}"
STANDALONE_APP_NAME='foobar'
STATIC_URL = '/static/'
sys.path.insert(0, f"{PARENT_DIR}/django-foo")
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.admin',
'django.contrib.messages',
'django.contrib.humanize',
'django.contrib.sites',
'django_nyt.apps.DjangoNytConfig',
'notifications',
STANDALONE_APP_NAME,
'myapp',
]
SECRET_KEY="lskfjklsdfjalkfslfjslfksdjfslkfslkfj"
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
DEBUG=True
# AUTH_USER_MODEL='testdata.CustomUser',
DATABASES={
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': f"{BASE_DIR}/db.sqlite3",
},
}
SITE_ID=1
ROOT_URLCONF=f"{SAMPLE_PROJECT_DIR_NAME}.urls"
TEMPLATES=[
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.messages.context_processors.messages',
]
},
},
]
USE_TZ=True
MIDDLEWARE=[
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
]
FOOBAR_DATA={}
settings.configure(
SECRET_KEY=SECRET_KEY,
DEFAULT_AUTO_FIELD = DEFAULT_AUTO_FIELD,
DEBUG=DEBUG,
# AUTH_USER_MODEL=AUTH_USER_MODEL,
DATABASES=DATABASES,
SITE_ID=SITE_ID,
ROOT_URLCONF=ROOT_URLCONF,
INSTALLED_APPS=INSTALLED_APPS,
STATIC_URL=STATIC_URL,
TEMPLATES=TEMPLATES,
USE_TZ=USE_TZ,
MIDDLEWARE=MIDDLEWARE,
FOOBAR_DATA = FOOBAR_DATA,
)
manage.py (same for both foo and foobar standalone applications)
import os
import sys
import django
from common import *
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), SAMPLE_PROJECT_DIR_NAME))
django.setup()
if __name__ == '__main__':
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
I have looked in the migrations folders for both applications and this is what I found:
- foo app has the migration
0010_auto_20220802_2211
generated, and applied to django_nyt, to change the PK auto fields to use BigInteger. - foobar app does not have the migration file
0010_auto_20220802_2211
generated for django_nyt (hence the migration error). I can't for the life of me, work out why foobar is not using the migrations generated by foo, since it has a dependency on foo.
A no-brainer hack would be to simply copy over the missing migration file, but that is too fragile, and I want to actually understand what is going on, and why foobar is not using/applying the migrations created by a dependency.
This is what I have tried so far (did not resolve the issue):
- I checked in the migration files for
foo
. Initially, I had kept them out of the repository - Created a dummy model class in foobar, that explicitly had a dependency on a model in dyango_nyt - the reasoning being that, if a django_nyt model existed in foobar, i would force migrations to be created for django_nyt.
This is what my dummy class in foobar/models.py
looked like:
from django_nyt.models import Notification
class FooBarMigrationHack(Notification):
name = models.CharField(max_length=10)
None of the above has worked, and I'm still getting the same error stack trace as shown above, in my question.
How do I resolve this without having to manually copy the 'missing' migration file from foo/migrations/
to foobar/migrations/
?
from Django standalone apps with one app depending on another app - django.db.migrations.exceptions.NodeNotFoundError
No comments:
Post a Comment