Problem with migrate, custom user model

Earlier I had run the official get started tutorial (and some other tutorial) without to much problem

Now I’ m trying to do a project for test some ideas. The project including a custom user model and I can´t get the migrate command to work.

All help is appreciated.

I can do:
python manage.py runserver (18 unapplied migration(s))
python manage.py check
python manage.py dbshell
python manage.py makemigrations
without any problem, but when I do python manage.py migrate i got “ValueError: Related model ‘core_account.customuser’ cannot be resolved” All errors below

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, core_account, sessions
Running migrations:
  Applying admin.0001_initial...Traceback (most recent call last):
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/manage.py", line 22, in <module>
    main()
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/core/management/base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/core/management/base.py", line 458, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/core/management/base.py", line 106, in wrapper
    res = handle_func(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/core/management/commands/migrate.py", line 356, in handle
    post_migrate_state = executor.migrate(
                         ^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/migrations/executor.py", line 135, in migrate
    state = self._migrate_all_forwards(
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/migrations/executor.py", line 167, in _migrate_all_forwards
    state = self.apply_migration(
            ^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/migrations/executor.py", line 252, in apply_migration
    state = migration.apply(state, schema_editor)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/migrations/migration.py", line 132, in apply
    operation.database_forwards(
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/migrations/operations/models.py", line 96, in database_forwards
    schema_editor.create_model(model)
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/backends/base/schema.py", line 448, in create_model
    sql, params = self.table_sql(model)
                  ^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/backends/base/schema.py", line 218, in table_sql
    definition, extra_params = self.column_sql(model, field)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/backends/base/schema.py", line 352, in column_sql
    field_db_params = field.db_parameters(connection=self.connection)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/models/fields/related.py", line 1166, in db_parameters
    target_db_parameters = self.target_field.db_parameters(connection)
                           ^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/models/fields/related.py", line 1059, in target_field
    return self.foreign_related_fields[0]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/utils/functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/models/fields/related.py", line 746, in foreign_related_fields
    rhs_field for lhs_field, rhs_field in self.related_fields if rhs_field
                                          ^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/utils/functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/models/fields/related.py", line 733, in related_fields
    return self.resolve_related_fields()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/models/fields/related.py", line 1086, in resolve_related_fields
    related_fields = super().resolve_related_fields()
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jan-ola/synchronizing/family/web_development/django/django_0005/.venv/lib/python3.11/site-packages/django/db/models/fields/related.py", line 711, in resolve_related_fields
    raise ValueError(
ValueError: Related model 'core_account.customuser' cannot be resolved

The custom user model is for more flexibility in the longer run, case insensitive about user name & e-mail adress, username of ASCII type and that e-mail shall be required.
The custom user model is in apps_core/core_account

I had a “base_settings.py” file with most settings and a “local_settings.py” with a few settings

File base_settings.py below:

Django settings for project.

Generated by 'django-admin startproject' using Django 4.2.3.

For more information on this file, see


For the full list of settings and their values, see

"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production


# SECURITY WARNING: keep the secret key used in production secret!
with open("project/settings/secret_key.txt") as f:
   SECRET_KEY = f.read().strip()


# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django_extensions',
    "apps_core.core_gis.apps.CoreGisConfig",
    "apps_core.core_account.apps.CoreAccountConfig",
    "apps_core.core_static.apps.CoreStaticConfig", # A template directory, not an app.
    "apps_optional.optional_polls.apps.OptionalPollsConfig",
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]

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 = "project.urls"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "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 = "project.wsgi.application"


# Database




# DATABASES = {
#     "default": {
#         "ENGINE": "django.db.backends.sqlite3",
#         "NAME": BASE_DIR / "db.sqlite3",
#     }
# }


# Using postgresql, settings for it is handle in other settings files. 

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "DATABASENAME",
        "USER": "DATABASE_USER",
        "PASSWORD": "USER_PASSWORD",
        "HOST": "127.0.0.1",
        "PORT": "5432",
    }
}

# Password validation


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",
    },
]


AUTH_USER_MODEL = "core_account.CustomUser"

# Internationalization


LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)


STATIC_URL = "static/"

# Default primary key field type


DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

Models file apps_core/core:account/models.py below:

from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin, UserManager
from django.contrib.auth.validators import ASCIIUsernameValidator
from django.core.mail import send_mail
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _


class CustomUser(AbstractBaseUser, PermissionsMixin):
    username_validator = ASCIIUsernameValidator()

    username = models.CharField(
        _("username"),
        max_length=150,
        db_collation="case_insensitiv",
        unique=True,
        help_text=_("Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."),
        validators=[username_validator],
        error_messages={
            "unique": _("A user with that username already exists."),
        },
    )
    first_name = models.CharField(_("first name"), max_length=150, blank=True)
    last_name = models.CharField(_("last name"), max_length=150, blank=True)
    email = models.EmailField(
        _("email address"),
        db_collation="case_insensitiv",
        unique=True,
        error_messages={
            "unique": _("A user with that email address already exists."),
        },
    )
    is_staff = models.BooleanField(
        _("staff status"),
        default=False,
        help_text=_("Designates whether the user can log into this admin site."),
    )
    is_active = models.BooleanField(
        _("active"),
        default=True,
        help_text=_(
            "Designates whether this user should be treated as active. Unselect this instead of deleting accounts."
        ),
    )
    date_joined = models.DateTimeField(_("date joined"), default=timezone.now)

    objects = UserManager()

    EMAIL_FIELD = "email"
    USERNAME_FIELD = "username"
    REQUIRED_FIELDS = ["email"]

    class Meta:
        verbose_name = _("user")
        verbose_name_plural = _("users")

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

    def get_full_name(self):
        """
        Return the first_name plus the last_name, with a space in between.
        """
        full_name = "%s %s" % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        """Return the short name for the user."""
        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        send_mail(subject, message, from_email, [self.email], **kwargs)

Migrationsfile “0001_postgres_extensions.py” below"

# Generated by Django 4.2.3 on 2023-07-18 19:39

from django.contrib.postgres.operations import CreateCollation
from django.db import migrations

class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        CreateCollation(
            "case_insensitive",
            provider="icu",
            locale="sv-u-ks-level2-kn-true",
            deterministic=False,
        ),
    ]

Tree structure below;

|-- apps_core
|   |-- core_account
|   |   |-- __pycache__
|   |   |   |-- __init__.cpython-311.pyc
|   |   |   |-- admin.cpython-311.pyc
|   |   |   |-- apps.cpython-311.pyc
|   |   |   `-- models.cpython-311.pyc
|   |   |-- migrations
|   |   |   |-- __pycache__
|   |   |   |   |-- 0001_initial.cpython-311.pyc
|   |   |   |   |-- 0001_postgres_extensions.cpython-311.pyc
|   |   |   |   |-- 0002_initial.cpython-311.pyc
|   |   |   |   `-- __init__.cpython-311.pyc
|   |   |   |-- 0001_postgres_extensions.py
|   |   |   |-- 0002_initial.py
|   |   |   `-- __init__.py
|   |   |-- tmp_migrations
|   |   |-- __init__.py
|   |   |-- admin.py
|   |   |-- apps.py
|   |   |-- models.py
|   |   |-- tests.py
|   |   `-- views.py
|   |-- core_gis
|   |   |-- __pycache__
|   |   |   |-- __init__.cpython-311.pyc
|   |   |   |-- admin.cpython-311.pyc
|   |   |   |-- apps.cpython-311.pyc
|   |   |   `-- models.cpython-311.pyc
|   |   |-- migrations
|   |   |   |-- __pycache__
|   |   |   |   `-- __init__.cpython-311.pyc
|   |   |   `-- __init__.py
|   |   |-- __init__.py
|   |   |-- admin.py
|   |   |-- apps.py
|   |   |-- models.py
|   |   |-- tests.py
|   |   `-- views.py
|   `-- core_static
|       |-- __pycache__
|       |   |-- __init__.cpython-311.pyc
|       |   |-- admin.cpython-311.pyc
|       |   |-- apps.cpython-311.pyc
|       |   `-- models.cpython-311.pyc
|       |-- migrations
|       |   |-- __pycache__
|       |   |   `-- __init__.cpython-311.pyc
|       |   `-- __init__.py
|       |-- __init__.py
|       |-- admin.py
|       |-- apps.py
|       |-- models.py
|       |-- tests.py
|       `-- views.py
|-- apps_optional
|   `-- optional_polls
|       |-- __pycache__
|       |   |-- __init__.cpython-311.pyc
|       |   |-- admin.cpython-311.pyc
|       |   |-- apps.cpython-311.pyc
|       |   `-- models.cpython-311.pyc
|       |-- migrations
|       |   |-- __pycache__
|       |   |   `-- __init__.cpython-311.pyc
|       |   `-- __init__.py
|       |-- __init__.py
|       |-- admin.py
|       |-- apps.py
|       |-- models.py
|       |-- tests.py
|       `-- views.py
|-- project
|   |-- __pycache__
|   |   |-- __init__.cpython-311.pyc
|   |   |-- urls.cpython-311.pyc
|   |   `-- wsgi.cpython-311.pyc
|   |-- settings
|   |   |-- __pycache__
|   |   |   |-- __init__.cpython-311.pyc
|   |   |   |-- base_settings.cpython-311.pyc
|   |   |   `-- local_settings.cpython-311.pyc
|   |   |-- __init__.py
|   |   |-- base_settings.py
|   |   |-- local_settings.py
|   |   `-- secret_key.txt
|   |-- __init__.py
|   |-- asgi.py
|   |-- urls.py
|   `-- wsgi.py
`-- manage.py

24 directories, 68 files

You’re going to end up encountering a number of different “odd” issues by trying to structure your project like this.

Until you get to the point where you understand how Django does things internally, I’d suggest you stick with the standard directory structure:

project_dir
| -- project
| -- app_dir_1
| -- app_dir_2
| -- static
| -- templates
...
1 Like

Thank you
I got it to work with “a more standard structure”:
´´´
├── app_core_accounts
│ ├── init.py
│ ├── pycache
│ │ ├── init.cpython-311.pyc
│ │ ├── admin.cpython-311.pyc
│ │ ├── apps.cpython-311.pyc
│ │ └── models.cpython-311.pyc
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_postgres_extensions.py
│ │ ├── 0002_initial.py
│ │ ├── init.py
│ │ └── pycache
│ │ ├── 0001_postgres_extensions.cpython-311.pyc
│ │ ├── 0002_initial.cpython-311.pyc
│ │ └── init.cpython-311.pyc
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── app_core_gis
│ ├── init.py
│ ├── pycache
│ │ ├── init.cpython-311.pyc
│ │ ├── admin.cpython-311.pyc
│ │ ├── apps.cpython-311.pyc
│ │ └── models.cpython-311.pyc
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── init.py
│ │ └── pycache
│ │ └── init.cpython-311.pyc
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── app_optional_polls
│ ├── init.py
│ ├── pycache
│ │ ├── init.cpython-311.pyc
│ │ ├── admin.cpython-311.pyc
│ │ ├── apps.cpython-311.pyc
│ │ └── models.cpython-311.pyc
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── init.py
│ │ └── pycache
│ │ └── init.cpython-311.pyc
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── manage.py
├── project
│ ├── init.py
│ ├── pycache
│ │ ├── init.cpython-311.pyc
│ │ ├── urls.cpython-311.pyc
│ │ └── wsgi.cpython-311.pyc
│ ├── asgi.py
│ ├── settings
│ │ ├── init.py
│ │ ├── pycache
│ │ │ ├── init.cpython-311.pyc
│ │ │ ├── base_settings.cpython-311.pyc
│ │ │ └── local_settings.cpython-311.pyc
│ │ ├── base_settings.py
│ │ ├── local_settings.py
│ │ └── secret_key.txt
│ ├── urls.py
│ └── wsgi.py
├── static
└── templates

19 directories, 55 files
´´´

One fault I did previously was a misspelling of “case_insensitive”. Had spellt it “case_insensitiv” in models.py.

Now it is passing database migration and I’m able to create superuser.