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.