Having django.db.utils.OperationalError: (1824, "Failed to open the referenced table 'auth_group'")

I am having an error on django when I run the code.

python manage.py test

The error is :

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/utils.py", line 103, in _execute
    return self.cursor.execute(sql)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/mysql/base.py", line 76, in execute
    return self.cursor.execute(query, args)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/cursors.py", line 179, in execute
    res = self._query(mogrified_query)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/cursors.py", line 330, in _query
    db.query(q)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/connections.py", line 280, in query
    _mysql.connection.query(self, query)
MySQLdb.OperationalError: (1824, "Failed to open the referenced table 'auth_group'")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/app/manage.py", line 22, in <module>
    main()
  File "/app/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/test.py", line 24, in run_from_argv
    super().run_from_argv(argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 416, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 460, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/test.py", line 63, in handle
    failures = test_runner.run_tests(test_labels)
  File "/usr/local/lib/python3.10/site-packages/django/test/runner.py", line 1092, in run_tests
    old_config = self.setup_databases(
  File "/usr/local/lib/python3.10/site-packages/django/test/runner.py", line 990, in setup_databases
    return _setup_databases(
  File "/usr/local/lib/python3.10/site-packages/django/test/utils.py", line 204, in setup_databases
    connection.creation.create_test_db(
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/creation.py", line 78, in create_test_db
    call_command(
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 194, in call_command
    return command.execute(*args, **defaults)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 460, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 107, in wrapper
    res = handle_func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/migrate.py", line 318, in handle
    self.sync_apps(connection, executor.loader.unmigrated_apps)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/migrate.py", line 465, in sync_apps
    with connection.schema_editor() as editor:
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/schema.py", line 169, in __exit__
    self.execute(sql, None)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/schema.py", line 204, in execute
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/utils.py", line 79, in execute
    return self._execute_with_wrappers(
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/utils.py", line 100, in _execute
    with self.db.wrap_database_errors:
  File "/usr/local/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/utils.py", line 103, in _execute
    return self.cursor.execute(sql)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/mysql/base.py", line 76, in execute
    return self.cursor.execute(query, args)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/cursors.py", line 179, in execute
    res = self._query(mogrified_query)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/cursors.py", line 330, in _query
    db.query(q)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/connections.py", line 280, in query
    _mysql.connection.query(self, query)
django.db.utils.OperationalError: (1824, "Failed to open the referenced table 'auth_group'")

Here are my tables in mysql:

+------------------------+
| Tables_in_main_db      |
+------------------------+
| Achievements           |
| Challenges             |
| Comments               |
| Posts                  |
| Tips                   |
| UserAchievements       |
| UserChallenges         |
| Users                  |
| auth_group             |
| auth_group_permissions |
| auth_permission        |
| authtoken_token        |
| django_admin_log       |
| django_content_type    |
| django_migrations      |
| django_session         |
+------------------------+

And also my settings, models and tests file:

Settings:

from pathlib import Path
from datetime import timedelta

# 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/5.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
# There is actually a secret key here I deleted it for this post
# SECURITY WARNING: don't run with debug turned on in production!

DEBUG = False

# I also removed allowed hosts from here for same reason


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'api',

    # third-party apps
    'rest_framework',
    'rest_framework.authtoken',
    'corsheaders',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    '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',
]

# I removed CORS_ALLOWED_ORIGINS from her efor this post
"""
CORS_ALLOW_ALL_ORIGINS = True

CORS_PREFLIGHT_MAX_AGE = 86400  # 24 hours
CORS_ALLOW_CREDENTIALS = True
CORS_EXPOSE_HEADERS = ['Content-Type', 'X-CSRFToken']

AUTH_USER_MODEL = 'api.Users'

ROOT_URLCONF = 'project.urls'

REST_FRAMEWORK = {
    "NON_FIELD_ERRORS_KEY": "errors",
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework.authentication.SessionAuthentication",
        "rest_framework.authentication.TokenAuthentication",
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ),
    "DEFAULT_PERMISSION_CLASSES": (
        "rest_framework.permissions.IsAuthenticated",
        'rest_framework.permissions.AllowAny',
    ),
}

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(days=36500),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=36500),
    "SIGNING_KEY": SECRET_KEY,
    "AUTH_HEADER_TYPES": ("Bearer",),
}

MIGRATION_MODULES = {
    'api': None,    # or whatever your app label is
}

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'project.wsgi.application'


# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'main_db',
        'USER': 'root',
        'PASSWORD': '123456789',
        'HOST': 'backend-db-1',  
        'PORT': '3306',       
        'OPTIONS': {
            'charset': 'utf8mb4',
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}


# Password validation
# https://docs.djangoproject.com/en/5.2/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/5.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

models.py:

from django.db import models
from django.contrib.auth.base_user import BaseUserManager
from django.contrib.auth.models import AbstractUser

class CustomUserManager(BaseUserManager):
    def create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError("The Email field must be set")
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('isAdmin', True)
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('isAdmin') is not True:
            raise ValueError('Superuser must have isAdmin=True.')
        return self.create_user(email, password, **extra_fields)


class Users(AbstractUser):
    class Meta:
        db_table = 'Users'

    # Primary key
    id = models.AutoField(primary_key=True)
    email = models.EmailField(max_length=100, unique=True)
    username = models.CharField(max_length=50, unique=True)
    password = models.CharField(max_length=100)

    # Additional columns
    isAdmin = models.BooleanField(default=False, db_column='isAdmin')
    profile_id = models.IntegerField(unique=True, null=True, blank=True)
    profile_image = models.CharField(max_length=255, null=True, blank=True)
    bio = models.TextField(null=True, blank=True)

    # Keep Django’s staff/superuser flags in sync if you need them
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    def __str__(self):
        return self.username

class Achievements(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)
    icon = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        db_table = 'Achievements'


class Challenges(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)
    target_amount = models.FloatField(blank=True, null=True)
    current_progress = models.FloatField(blank=True, null=True)
    is_public = models.IntegerField(blank=True, null=True)
    reward = models.ForeignKey(Achievements, models.DO_NOTHING, blank=True, null=True)

    class Meta:
        db_table = 'Challenges'


class Comments(models.Model):
    post = models.ForeignKey('Posts', models.DO_NOTHING)
    author = models.ForeignKey('Users', models.DO_NOTHING)
    content = models.TextField()
    date = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'Comments'


class Posts(models.Model):
    creator = models.ForeignKey('Users', models.DO_NOTHING)
    date = models.DateTimeField(blank=True, null=True)
    text = models.TextField(blank=True, null=True)
    image = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        db_table = 'Posts'


class Tips(models.Model):
    text = models.TextField()
    like_count = models.IntegerField(blank=True, null=True)
    dislike_count = models.IntegerField(blank=True, null=True)

    class Meta:
        db_table = 'Tips'


class UserAchievements(models.Model):
    user = models.ForeignKey('Users', models.DO_NOTHING)
    achievement = models.ForeignKey(Achievements, models.DO_NOTHING)
    earned_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'UserAchievements'
        unique_together = (('user', 'achievement'),) # these two together becomes primary key


class UserChallenges(models.Model):
    user = models.ForeignKey('Users', models.DO_NOTHING)
    challenge = models.ForeignKey(Challenges, models.DO_NOTHING)
    joined_date = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'UserChallenges'
        unique_together = (('user', 'challenge'),) # these two together becomes primary key

test:

from django.test import TestCase
from django.contrib.auth import get_user_model
from rest_framework import status
from rest_framework.exceptions import ValidationError
from rest_framework.authtoken.models import Token
from rest_framework.test import APIRequestFactory, force_authenticate

from api.login_and_signup.login_serializer import LoginSerializer
from api.login_and_signup.login_views import (
    SignUpView, LoginView, server_status, get_user_info
)
from api.login_and_signup.tokens import create_jwt_pair_for_user

User = get_user_model()


class LoginSerializerTests(TestCase):
    def test_validate_success(self):
        data = {
            "email": "new@example.com",
            "username": "newuser",
            "password": "password123"
        }
        serializer = LoginSerializer(data=data)
        self.assertTrue(serializer.is_valid(), serializer.errors)
        validated = serializer.validated_data
        self.assertEqual(validated["email"], data["email"])
        self.assertEqual(validated["username"], data["username"])

    def test_validate_email_exists(self):
        User.objects.create(email="exists@example.com", username="u1", password="x")
        data = {
            "email": "exists@example.com",
            "username": "otheruser",
            "password": "password123"
        }
        serializer = LoginSerializer(data=data)
        with self.assertRaises(ValidationError):
            serializer.is_valid(raise_exception=True)

    def test_validate_username_exists(self):
        User.objects.create(email="u2@example.com", username="existsuser", password="x")
        data = {
            "email": "unique@example.com",
            "username": "existsuser",
            "password": "password123"
        }
        serializer = LoginSerializer(data=data)
        with self.assertRaises(ValidationError):
            serializer.is_valid(raise_exception=True)

    def test_create_user_and_token(self):
        before = User.objects.count()
        data = {
            "email": "create@example.com",
            "username": "createuser",
            "password": "password123"
        }
        serializer = LoginSerializer(data=data)
        self.assertTrue(serializer.is_valid(raise_exception=True))
        user = serializer.save()
        # user created
        self.assertEqual(User.objects.count(), before + 1)
        self.assertEqual(user.email, data["email"])
        self.assertEqual(user.username, data["username"])
        # password is hashed
        self.assertTrue(user.check_password(data["password"]))
        # authtoken created
        self.assertTrue(Token.objects.filter(user=user).exists())


class SignUpViewTests(TestCase):
    def setUp(self):
        self.factory = APIRequestFactory()
        self.view = SignUpView.as_view()

    def test_signup_success(self):
        data = {
            "email": "signup@example.com",
            "username": "signupuser",
            "password": "password123"
        }
        req = self.factory.post("/signup/", data, format="json")
        resp = self.view(req)
        self.assertEqual(resp.status_code, status.HTTP_201_CREATED)
        self.assertEqual(resp.data["message"], "User created successfully.")
        self.assertEqual(resp.data["data"]["email"], data["email"])
        self.assertEqual(resp.data["data"]["username"], data["username"])

    def test_signup_fails_on_existing_email(self):
        User.objects.create(email="a@example.com", username="u1", password="x")
        data = {
            "email": "a@example.com",
            "username": "newuser",
            "password": "password123"
        }
        req = self.factory.post("/signup/", data, format="json")
        resp = self.view(req)
        self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
        # error comes back under non_field_errors
        self.assertIn("Email already exists.", str(resp.data))

    def test_signup_fails_on_existing_username(self):
        User.objects.create(email="b@example.com", username="bob", password="x")
        data = {
            "email": "unique@example.com",
            "username": "bob",
            "password": "password123"
        }
        req = self.factory.post("/signup/", data, format="json")
        resp = self.view(req)
        self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn("Username already exists.", str(resp.data))


class LoginViewTests(TestCase):
    def setUp(self):
        self.factory = APIRequestFactory()
        # create user and set password
        self.user = User.objects.create(email="login@example.com", username="loginuser")
        self.user.set_password("password123")
        self.user.save()
        self.view = LoginView.as_view()

    def test_login_success(self):
        data = {"email": "login@example.com", "password": "password123"}
        req = self.factory.post("/login/", data, format="json")
        resp = self.view(req)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.data["message"], "Login successful.")
        tokens = resp.data["token"]
        self.assertIn("access", tokens)
        self.assertIn("refresh", tokens)

    def test_login_failure(self):
        data = {"email": "login@example.com", "password": "wrongpass"}
        req = self.factory.post("/login/", data, format="json")
        resp = self.view(req)
        self.assertEqual(resp.status_code, status.HTTP_401_UNAUTHORIZED)
        self.assertEqual(resp.data, {"error": "Invalid credentials!"})

    def test_get_authenticated_user_info(self):
        req = self.factory.get("/login/")
        # simulate DRF authentication
        force_authenticate(req, user=self.user)
        resp = self.view(req)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.data["user"], str(self.user))
        # when using force_authenticate without token, auth is None
        self.assertIn("auth", resp.data)


class ServerStatusTests(TestCase):
    def setUp(self):
        self.factory = APIRequestFactory()

    def test_server_status(self):
        req = self.factory.get("/status/")
        print("Request object:", req)  # Inspect the request
        resp = server_status(req)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.data, {"status": "Server is running"})


class GetUserInfoTests(TestCase):
    def setUp(self):
        self.factory = APIRequestFactory()
        self.user = User.objects.create(email="info@example.com", username="infouser")
        self.user.set_password("password123")
        self.user.save()

    def test_protected_endpoint_with_auth(self):
        req = self.factory.get("/user-info/")
        force_authenticate(req, user=self.user)
        resp = get_user_info(req)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.data, {
            "username": self.user.username,
            "is_authenticated": True
        })

    def test_protected_endpoint_without_auth(self):
        req = self.factory.get("/user-info/")
        resp = get_user_info(req)
        # either 401 or 403 depending on your authentication setup
        self.assertIn(resp.status_code, (
            status.HTTP_401_UNAUTHORIZED,
            status.HTTP_403_FORBIDDEN
        ))


class JWTTokenTests(TestCase):
    def test_create_jwt_pair_for_user(self):
        user = User.objects.create(email="tok@example.com", username="tokuser")
        pair = create_jwt_pair_for_user(user)
        self.assertIn("access", pair)
        self.assertIn("refresh", pair)
        self.assertIsInstance(pair["access"], str)
        self.assertIsInstance(pair["refresh"], str)

I am a rookie in django and backend development generally. Sorry if I missed a basic point or something fundamental.