Deployed Django Rest Framework API gives "Server got itself in trouble" on any call with payload
I am deploying my Django Rest API to a web server running on Ubuntu 24.04 LTS Linux and using the Apache web server. This web server is external; I have not set it up, and so some of the details on how it works is a blackbox to me.
I have run into a very annoying error in which I will get a 500 error saying "Server got itself in trouble" whenever I add payload to any sort of request. It doesn't matter the method: it can be a GET, POST, PUT, PATCH or DELETE and it will still run into the error...
However, when I run a request without a payload, I don't run into this error (I run into expected errors for not including expected request data instead)...
Here are some details on the server, that could give insight:
- The app runs within a Gunicorn container
- Client requests go to a reverse proxy and they are redirected to the app
- The app handles incoming requests and is listening out for them
Here is also the settings.py I am using. I have DEBUG=True for now to try to get to the root of the issue...
"""
Django settings for server project.
Generated by 'django-admin startproject' using Django 5.1.4.
For more information on this file, see
https://docs.djangoproject.com/en/5.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.1/ref/settings/
"""
from pathlib import Path
from datetime import timedelta
from cryptography.fernet import Fernet
import sys
import environ
import os
env = environ.Env()
environ.Env.read_env()
USE_X_FORWARDED_HOST = True
# 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.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-(ltwgqma)#6=y3!dcw4b&8sog&%y@i51d1ye*(w_fk$9p0tvip'
ENCRYPTED_FIELDS_KEY = env('ENCRYPTED_FIELDS_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'daphne',
'django_eventstream',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'django_apscheduler',
'rest_framework',
'rest_framework_simplejwt.token_blacklist',
'corsheaders',
'apps.api'
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'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 = 'server.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 = 'server.wsgi.application'
ASGI_APPLICATION = "server.asgi.application"
# Database
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'server.com',
'NAME': env('DB_NAME'),
'USER': env('DB_USERNAME'),
'PASSWORD': env('DB_PASSWORD')
}
}
# Password validation
# https://docs.djangoproject.com/en/5.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',
},
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
FIXTURE_DIRS = [
'fixtures'
]
STATIC_URL = 'static/'
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "server/media")
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
CORS_ALLOW_ALL_ORIGINS = True
AUTH_USER_MODEL = "users.User"
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
],
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
]
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=10),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': False,
'USER_ID_FIELD': 'user_id'
}
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {
"class": "logging.StreamHandler",
},
},
"root": {
"handlers": ["console"],
"level": "WARNING",
},
}
if 'test' in sys.argv:
DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'test'
}
There are logs I can access, but there is nothing there other than api/users 404: Bad request
that indicate the error.
Thank you to anyone who can help me get to the bottom on this!
The error appears to be occurring because the view isn't checking if the user is authenticated before accessing its attributes. Django uses AnonymousUser to handle unauthenticated user sessions, and this model doesn't have a user_id field, which is causing the 500 error.
Check your view to see if you're ensuring the user is authenticated before attempting to access the user_id. Something like this might help:
if not request.user.is_authenticated:
return JsonResponse({"error": "User not authenticated"}, status=401)
However, to help you better, could you share the code for your full view? Specifically, how you're getting the user and accessing their attributes.