Hey All,
I’ve run into an error that makes me believe my customuser model is not migrating.
I’m using Docker to run my Django app, PostgreSQL db, RabbitMQ broker, and Celery worker.
(string_v3) PS C:\Users\steve\Desktop\Coding\string_v3> docker-compose up -d --build
The app starts fine, but when I go to login, I get an error. The output from the logs is here:
Creating string_v3_db_1 ... done
Creating string_v3_web_1 ... done
Creating string_v3_rabbitmq_1 ... done
Creating string_v3_celeryworker_1 ... done
(string_v3) PS C:\Users\steve\Desktop\Coding\string_v3> docker-compose logs
Attaching to string_v3_celeryworker_1, string_v3_rabbitmq_1, string_v3_web_1, string_v3_db_1
db_1 |
db_1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
db_1 |
db_1 | 2021-10-03 12:51:22.015 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
db_1 | 2021-10-03 12:51:22.015 UTC [1] LOG: listening on IPv6 address "::", port 5432
db_1 | 2021-10-03 12:51:22.023 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1 | 2021-10-03 12:51:22.041 UTC [26] LOG: database system was shut down at 2021-09-25 18:03:18 UTC
db_1 | 2021-10-03 12:51:22.058 UTC [1] LOG: database system is ready to accept connections
db_1 | 2021-10-03 12:53:36.671 UTC [36] ERROR: relation "users_customuser" does not exist at character 387
Abbreviating some of the logs for brevity …
_1 | File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
web_1 | return self.cursor.execute(sql, params)
web_1 | django.db.utils.ProgrammingError: relation "users_customuser" does not exist
web_1 | LINE 1: SELECT (1) AS "a" FROM "users_customuser" WHERE "users_custo...
Most of what I could find suggested to re-run migrations. I shut down and run migrations:
(string_v3) PS C:\Users\steve\Desktop\Coding\string_v3> docker-compose down
Stopping string_v3_celeryworker_1 ... done
Stopping string_v3_rabbitmq_1 ... done
Stopping string_v3_web_1 ... done
Stopping string_v3_db_1 ... done
Removing string_v3_celeryworker_1 ... done
Removing string_v3_rabbitmq_1 ... done
Removing string_v3_web_1 ... done
Removing string_v3_db_1 ... done
Removing network string_v3_default
(string_v3) PS C:\Users\steve\Desktop\Coding\string_v3> docker-compose exec web python manage.py makemigrations
(string_v3) PS C:\Users\steve\Desktop\Coding\string_v3> docker-compose exec web python manage.py migrate
This doesn’t seem to solve my problem.
docker-comose.yml
version: '3.8'
services:
build: .
command: python /code/manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- 8000:8000
depends_on:
image: postgres:11
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
rabbitmq:
image: rabbitmq:3.8.18-management
hostname: rabbitmq
ports:
- 15672:15672
- 5672:5672
expose:
- 15672
depends_on:
- web
celeryworker:
build: .
depends_on:
- rabbitmq
command: celery -A string_project worker -l info --pool=solo
volumes:
postgres_data:
users/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class CustomUser(AbstractUser):
company=models.CharField(
max_length=100,
null=False, # false means value is needed in db
blank=False, #false means value is needed in forms
editable=True,
settings.py
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'removed'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*'] #added the star here based on recommendation from Docker. Needs to be removed for production.
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'users.apps.UsersConfig',
'pages.apps.PagesConfig',
'applications.apps.ApplicationsConfig'
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
ROOT_URLCONF = 'string_project.urls'
TEMPLATES = [
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
WSGI_APPLICATION = 'string_project.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': 'db',
'PORT': 5432
# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'America/New_York'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS=(str(BASE_DIR.joinpath('static')),)
STATIC_ROOT= str(BASE_DIR.joinpath('staticfiles'))
STATFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
AUTH_USER_MODEL='users.CustomUser'
LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'home'
CRISPY_TEMPLATE_PACK = 'bootstrap4'
# Email Config
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = 'removed'
EMAIL_HOST_PASSWORD = 'removed'
# Celery Config
CELERY_BROKER_URL = 'amqp://rabbitmq:5672/'
#CELERY_RESULT_BACKEND = 'amqp'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_AMQP_TASK_RESULT_EXPIRES = 1000
CELERY_ACKS_LATE=False
CELERY_TASK_TRACK_STARTED=True
CELERY_SEND_TASK_EVENTS=True
I don’t have anything I’m concerned about saving in any of my databases.
Does anyone see anything that would be causing my error?
Steve
Update:
Here are updated logs related to the makemigrations and migrate:
(string_v3) PS C:\Users\steve\Desktop\Coding\string_v3> docker-compose exec web python manage.py makemigrations
You are trying to change the nullable field 'company' on customuser to non-nullable without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Ignore for now, and let me handle existing rows with NULL myself (e.g. because you added a RunPython or RunSQL operation to handle NULL values in a previous data migration)
3) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
Invalid input: name 'Demo' is not defined
>>> 'Demo'
Migrations for 'users':
users/migrations/0004_auto_20211003_1233.py
- Alter field company on customuser
(string_v3) PS C:\Users\steve\Desktop\Coding\string_v3> docker-compose exec web python manage.py migrate
Operations to perform:
Apply all migrations: admin, applications, auth, contenttypes, sessions, users
Running migrations:
Applying users.0004_auto_20211003_1233...Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedTable: relation "users_customuser" does not exist
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 22, in <module>
main()
File "manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 330, in run_from_argv
self.execute(*args, **cmd_options)
File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 371, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 85, in wrapped
res = handle_func(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/core/management/commands/migrate.py", line 243, in handle
post_migrate_state = executor.migrate(
File "/usr/local/lib/python3.8/site-packages/django/db/migrations/executor.py", line 117, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/python3.8/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/python3.8/site-packages/django/db/migrations/executor.py", line 227, in apply_migration
state = migration.apply(state, schema_editor)
File "/usr/local/lib/python3.8/site-packages/django/db/migrations/migration.py", line 124, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "/usr/local/lib/python3.8/site-packages/django/db/migrations/operations/fields.py", line 236, in database_forwards
schema_editor.alter_field(from_model, from_field, to_field)
File "/usr/local/lib/python3.8/site-packages/django/db/backends/base/schema.py", line 571, in alter_field
self._alter_field(model, old_field, new_field, old_type, new_type,
File "/usr/local/lib/python3.8/site-packages/django/db/backends/postgresql/schema.py", line 166, in _alter_field
super()._alter_field(
File "/usr/local/lib/python3.8/site-packages/django/db/backends/base/schema.py", line 721, in _alter_field
self.execute(
File "/usr/local/lib/python3.8/site-packages/django/db/backends/base/schema.py", line 142, in execute
cursor.execute(sql, params)
File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", line 98, in execute
return super().execute(sql, params)
File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "users_customuser" does not exist
(string_v3) PS C:\Users\steve\Desktop\Coding\string_v3> docker-compose exec web python manage.py showmigrations
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
applications
[X] 0001_initial
[X] 0002_application_company
[X] 0003_application_file
[X] 0004_auto_20210515_2027
[X] 0005_auto_20210515_2106
[X] 0006_auto_20210516_1415
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
[X] 0012_alter_user_first_name_max_length
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
pages
(no migrations)
sessions
[X] 0001_initial
users
[X] 0001_initial
[X] 0002_customuser_company
[X] 0003_auto_20210103_1045
[ ] 0004_auto_20211003_1233
It looks to me like the last users migration file is not completing. This is the file that was created when I selected option 1 above. Here is the migration file:
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0003_auto_20210103_1045'),
operations = [
migrations.AlterField(
model_name='customuser',
name='company',
field=models.CharField(default='Demo', max_length=100),
preserve_default=False,
I switched from SQLite to PostgreSQL. It almost seems like my CustomUser model did not make the transfer?
First, you probably don’t want to do a “makemigrations” in the container. When you rebuild the container, migrations are likely to end up with different names, causing problem. The migration files should be part of your source being used to create the container.
Second, having a service “depends_on” a database service is not enough to ensure that the database is actually up and running when the dependent service starts. (The “service” can be up long before the database is actually available.) If your service needing the database doesn’t have a way of handling that condition, other problems will arise. See the docs for depends_on for more information.
Thanks Ken.
With the comment about depends_on, do you think I have a db startup error where PostgreSQL isn’t starting? I see now in the documents this line:
depends_on does not wait for db and redis to be “ready” before starting web - only until they have been started. If you need to wait for a service to be ready, see Controlling startup order for more on this problem and strategies for solving it.
If PostgreSQL started, but never got up and ‘ready’, should I see that in the logs?
I was following Will Vincent’s Django for Professionals on the makemigrations, but I’ll try to remake migrations outside of it.
Given where I’m at, would you suggest I just delete the current migration files and start over?
Steve
smeislahn:
Given where I’m at, would you suggest I just delete the current migration files and start over?
That seems to be the safest path from what I can see. (To be explicitly clear - actually running the migrations in the container is fine. It’s running makemigrations that can cause problems.)
smeislahn:
If PostgreSQL started, but never got up and ‘ready’, should I see that in the logs?
In general, yes - I would expect to see your app throwing a connection error if that’s what’s happening. (It might not show up in your docker logs if you’re using the python logging module and logging errors elsewhere. But I would expect them to be logged somewhere.)
smeislahn:
You are trying to change the nullable field 'company' on customuser to non-nullable without a default; we can't do that (the database needs something to populate existing rows).
This part of the log leads me to believe that there are existing entries in the CustomUser db. If I just delete the migration files, does it also clear the db, or do I need to do that somewhere as well?
Deleted all migrations in the folder except for __init__.py
Deleted all files in the migrations __pycache__ folder except for __init__.cpython-38.pyc
I did this for all models that had migrations.
I then tried to make migrations:
(string_v3) PS C:\Users\steve\Desktop\Coding\string_v3> python manage.py makemigrations
This is the output I got:
Traceback (most recent call last):
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\backends\base\base.py", line 219, in ensure_connection
self.connect()
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\utils\asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\backends\base\base.py", line 200, in connect
self.connection = self.get_new_connection(conn_params)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\utils\asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\backends\postgresql\base.py", line 187, in get_new_connection
connection = Database.connect(**conn_params)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\psycopg2\__init__.py", line 127, in connect
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not translate host name "db" to address: Unknown host
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 22, in <module>
main()
File "manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
utility.execute()
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\core\management\__init__.py", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\core\management\base.py", line 330, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\core\management\base.py", line 371, in execute
output = self.handle(*args, **options)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\core\management\base.py", line 85, in wrapped
res = handle_func(*args, **kwargs)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\core\management\commands\makemigrations.py", line 101, in handle
loader.check_consistent_history(connection)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\migrations\loader.py", line 290, in check_consistent_history
applied = recorder.applied_migrations()
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\migrations\recorder.py", line 77, in applied_migrations
if self.has_table():
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\migrations\recorder.py", line 55, in has_table
with self.connection.cursor() as cursor:
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\utils\asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\backends\base\base.py", line 259, in cursor
return self._cursor()
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\backends\base\base.py", line 235, in _cursor
self.ensure_connection()
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\utils\asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\backends\base\base.py", line 219, in ensure_connection
self.connect()
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\backends\base\base.py", line 219, in ensure_connection
self.connect()
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\utils\asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\backends\base\base.py", line 200, in connect
self.connection = self.get_new_connection(conn_params)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\utils\asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\django\db\backends\postgresql\base.py", line 187, in get_new_connection
connection = Database.connect(**conn_params)
File "C:\Users\steve\Desktop\Coding\string_v3\lib\site-packages\psycopg2\__init__.py", line 127, in connect
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
django.db.utils.OperationalError: could not translate host name "db" to address: Unknown host
I"m not sure if the error above is related to my previous errors, but it seems like it could be. I’d be interested in any input; in the meantime, I’ll be reading docs and googling. 
Steve
smeislahn:
psycopg2.OperationalError: could not translate host name "db" to address: Unknown host
Pretty straight forward.
Whatever you’re running this on doesn’t recognize db as a valid host name. As this is not a valid DNS entry, you would need to have this defined somewhere for local name resolution.
Your settings file looks like it’s set up to work within the docker environment, but you’re trying to run makemigrations from the command line.
So I ended up getting things back on track. I can’t say for sure what the root cause was, but in case anyone comes across this looking for a solution, here are the additional steps I took:
In settings.py, I switched back to sqlite db to run makemigrations, and that worked fine.
In settings.py, I switched back to postgreSQL, started my docker containers, then ran the migrate, and it worked fine.
The CustomUser model also migrated fine. A few pages I checked are working and all of my tests passed. My take away is that my root cause is likely related to Ken’s suggestion:
KenWhitesell:
First, you probably don’t want to do a “makemigrations” in the container. When you rebuild the container, migrations are likely to end up with different names, causing problem. The migration files should be part of your source being used to create the container.
Steve