Object of type datetime is not JSON serializable

I have implemented a particular type of User type which has a time limit and I thought the correct way to enforce that time-limit was to set a Session expiry to a given date/time (ie 2 hours in the future) - note I don’t want the session to close after 2 hours of inactivity.

I am therefore doing this in my view :

`request.session.set_expiry(timezone.now() + timedelta(hours=2))` 

I am using the default databased backed Session backend.

However this fails with the error :

Object of type datetime is not JSON serializable.

Now I understand that the Session backend uses Json serialisation, and I understand that JSON doesn’t have a datetime object, but the documentation clearly states that this should work.

So how do I set session expiry for 2 hours in the future (again not 2 hours of inactivity).

Please post the complete view, error message, and traceback.

Ken,

Posting the view is a challenge (due to the size) but I know that when i comment out the line that does request.session.set_expiry() i don’t get the error.

I also don’t get the error when i do :

request.session.set_expiry(120*60)

Although this gives me 2 hours of inactivity before the session expires which is not what i need.


This is the traceback and error

TypeError at /user/input_short_code/18/

Object of type datetime is not JSON serializable

Request Method: POST
Request URL: http://127.0.0.1:8000/user/input_short_code/18/?next=/location/view
Django Version: 4.0.6
Exception Type: TypeError
Exception Value: Object of type datetime is not JSON serializable
Exception Location: /usr/lib/python3.10/json/encoder.py, line 179, in default
Python Executable: /home/tony/.envs/GarageSaleWebSite/bin/python
Python Version: 3.10.12
Python Path: [‘/home/tony/Development/GarageSale’, ‘/home/tony/Development/GarageSale’, ‘/home/tony/Development/python/modules’, ‘/usr/lib/python310.zip’, ‘/usr/lib/python3.10’, ‘/usr/lib/python3.10/lib-dynload’, ‘/home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages’]
Server time: Tue, 05 Nov 2024 11:19:59 +0000

Traceback Switch to copy-and-paste view

  • /home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages/django/core/handlers/exception.py, line 55, in inner

    1. response = get_response(request)

Local vars

  • /home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages/django/utils/deprecation.py, line 136, in call

    1. response = self.process_response(request, response)

Local vars

  • /home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages/django/contrib/sessions/middleware.py, line 59, in process_response

    1. request.session.save()

Local vars

  • /home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages/django/contrib/sessions/backends/db.py, line 82, in save

    1. obj = self.create_model_instance(data)

Local vars

  • /home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages/django/contrib/sessions/backends/db.py, line 69, in create_model_instance

    1. session_data=self.encode(data),

Local vars

  • /home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages/django/contrib/sessions/backends/base.py, line 94, in encode

    1. return signing.dumps(

Local vars

  • /home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages/django/core/signing.py, line 142, in dumps

    1. return TimestampSigner(key, salt=salt).sign_object(

Local vars

  • /home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages/django/core/signing.py, line 201, in sign_object

    1. data = serializer().dumps(obj)

Local vars

  • /home/tony/.envs/GarageSaleWebSite/lib/python3.10/site-packages/django/core/signing.py, line 117, in dumps

    1. return json.dumps(obj, separators=(“,”, “:”)).encode(“latin-1”)

Local vars

  • /usr/lib/python3.10/json/__init__.py, line 238, in dumps

    1. **kw).encode(obj)

Local vars

  • /usr/lib/python3.10/json/encoder.py, line 199, in encode

    1. chunks = self.iterencode(o, _one_shot=True)

Local vars

  • /usr/lib/python3.10/json/encoder.py, line 257, in iterencode

    1. return _iterencode(o, 0)

Local vars

  • /usr/lib/python3.10/json/encoder.py, line 179, in default

    1. raise TypeError(f’Object of type {o.class.name} ’

Local vars

Variable Value
o datetime.datetime(2024, 11, 5, 13, 19, 59, 987798)
self <json.encoder.JSONEncoder object at 0x74c4464b0b50>

Request information

USER

test@test.com

GET

Variable Value
next ‘/location/view’

POST

Variable Value
csrfmiddlewaretoken ‘Kwky70QA2RxdOMBQuIDsd63INN3GCh1CeOjBTN8NsoDDUKq4s6FNXy7tGrKzWAx7’
email ‘test@test.com’
short_code ‘PSPYPXP’

FILES

No FILES data

COOKIES

Variable Value
csrftoken ‘TGq63BBaxnf3h3ct8x6Xkkld7rS9bCdVnYp9PoTnXUltn11H6V8i4MpY05z2vVJq’

META

Variable Value
CONTENT_LENGTH ‘125’
CONTENT_TYPE ‘application/x-www-form-urlencoded’
CSRF_COOKIE ‘LTsjEm7A64uC3aDfSSWPhm475qFELUnn8mXdOHEhFTvDouX48jsGqGf0sy3Qf9Bt’
CSRF_COOKIE_NEEDS_UPDATE False
CVSROOT ‘/usr/local/cvsroot’
DBUS_SESSION_BUS_ADDRESS ‘unix:path=/run/user/1000/bus’
DESKTOP_SESSION ‘ubuntu’
DISPLAY ‘:1’
DJANGO_SETTINGS_MODULE ‘GarageSale.settings’
DOTNET_BUNDLE_EXTRACT_BASE_DIR ‘/home/tony/.cache/dotnet_bundle_extract’
GATEWAY_INTERFACE ‘CGI/1.1’
GDMSESSION ‘ubuntu’
GIO_LAUNCHED_DESKTOP_FILE ‘/home/tony/Desktop/jetbrains-pycharm-ce.desktop’
GIO_LAUNCHED_DESKTOP_FILE_PID ‘9941’
GJS_DEBUG_OUTPUT ‘stderr’
GJS_DEBUG_TOPICS ‘JS ERROR;JS LOG’
GLADE_CATALOG_SEARCH_PATH ‘/home/tony/Development/python/pygtk-widgets/catalog’
GLADE_MODULE_SEARCH_PATH ‘~~/Development/python/pygtk-widgets/modules’
GNOME_DESKTOP_SESSION_ID ‘this-is-deprecated’
GNOME_SHELL_SESSION_MODE ‘ubuntu’
GPG_AGENT_INFO ‘/run/user/1000/gnupg/S.gpg-agent:0:1’
GTK3_MODULES ‘xapp-gtk3-module’
GTK_IM_MODULE ‘ibus’
GTK_MODULES ‘gail:atk-bridge’
HISTCONTROL ‘ignoreboth’
HOME ‘/home/tony’
HTTP_ACCEPT ‘text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7’
HTTP_ACCEPT_ENCODING ‘gzip, deflate, br, zstd’
HTTP_ACCEPT_LANGUAGE ‘en-GB,en-US;q=0.9,en;q=0.8’
HTTP_CACHE_CONTROL ‘max-age=0’
HTTP_CONNECTION ‘keep-alive’
HTTP_COOKIE ‘csrftoken=TGq63BBaxnf3h3ct8x6Xkkld7rS9bCdVnYp9PoTnXUltn11H6V8i4MpY05z2vVJq’
HTTP_HOST ‘127.0.0.1:8000’
HTTP_ORIGIN ‘http://127.0.0.1:8000
HTTP_REFERER ‘http://127.0.0.1:8000/user/input_short_code/18/?next=/location/view
HTTP_SEC_CH_UA ‘“Chromium”;v=“130”, “Google Chrome”;v=“130”, “Not?A_Brand”;v=“99”’
HTTP_SEC_CH_UA_MOBILE ‘?0’
HTTP_SEC_CH_UA_PLATFORM ‘“Linux”’
HTTP_SEC_FETCH_DEST ‘document’
HTTP_SEC_FETCH_MODE ‘navigate’
HTTP_SEC_FETCH_SITE ‘same-origin’
HTTP_SEC_FETCH_USER ‘?1’
HTTP_UPGRADE_INSECURE_REQUESTS ‘1’
HTTP_USER_AGENT (‘Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ’ ‘Chrome/130.0.0.0 Safari/537.36’)
IM_CONFIG_PHASE ‘1’
INVOCATION_ID ‘153afe5853434b64b965208848129937’
JOURNAL_STREAM ‘8:21941’
LANG ‘en_GB.UTF-8’
LANGUAGE ‘en_GB:en’
LESSCLOSE ‘/usr/bin/lesspipe %s %s’
LESSOPEN ’ /usr/bin/lesspipe %s’
LOGNAME ‘tony’
LS_COLORS ‘rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.zst=01;31:.tzst=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.wim=01;31:.swm=01;31:.dwm=01;31:.esd=01;31:.jpg=01;35:.jpeg=01;35:.mjpg=01;35:.mjpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.webp=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:’
MANAGERPID ‘2136’
PATH ‘/home/tony/.envs/GarageSaleWebSite/bin:/home/tony/.local/bin:.:/home/tony/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/home/tony/.dotnet/tools:/home/tony/.local/share/JetBrains/Toolbox/scripts’
PATH_INFO ‘/user/input_short_code/18/’
PROMPT_COMMAND ‘set_prompt’
PS1 ('(GarageSaleWebSite) \[\033[0;37m\]$(date +%H:%M) ’ '\[\033[0;32m\]\u@\h: \[\033[0;35m\]\W ’ '\[\033[0;33m\]\[\033[0;33m\](* single-location-form) ’ ‘\[\033[0;92m\]$ \[\033[0;97m\] ‘)
PWD ‘/home/tony/Development/GarageSale’
PYTHONPATH ‘:/home/tony/Development/python/modules’
PYTHONSTARTUP ‘/home/tony/Development/python/startup.py’
QT_ACCESSIBILITY ‘1’
QT_IM_MODULE ‘ibus’
QUERY_STRING ‘next=/location/view’
REMOTE_ADDR ‘127.0.0.1’
REMOTE_HOST ‘’
REQUEST_METHOD ‘POST’
RUN_MAIN ‘true’
SCRIPT_NAME ‘’
SERVER_NAME ‘localhost’
SERVER_PORT ‘8000’
SERVER_PROTOCOL ‘HTTP/1.1’
SERVER_SOFTWARE ‘WSGIServer/0.2’
SESSION_MANAGER ‘local/Laptop:@/tmp/.ICE-unix/2375,unix/Laptop:/tmp/.ICE-unix/2375’
SHELL ‘/bin/bash’
SHLVL ‘1’
SSH_AGENT_LAUNCHER ‘gnome-keyring’
SSH_AUTH_SOCK ‘/run/user/1000/keyring/ssh’
SYSTEMD_EXEC_PID ‘2399’
TERM ‘xterm-256color’
TERMINAL_EMULATOR ‘JetBrains-JediTerm’
TERM_SESSION_ID ‘361d9afa-475c-4737-b62d-99371e5078bf’
TZ ‘UTC’
USER ‘tony’
USERNAME ‘tony’
VIRTUALENVWRAPPER_HOOK_DIR ‘/home/tony/.envs’
VIRTUALENVWRAPPER_PROJECT_FILENAME ‘.project’
VIRTUALENVWRAPPER_PYTHON ‘/usr/bin/python3’
VIRTUALENVWRAPPER_SCRIPT ‘/usr/local/bin/virtualenvwrapper.sh’
VIRTUALENVWRAPPER_WORKON_CD ‘1’
VIRTUAL_ENV ‘/home/tony/.envs/GarageSaleWebSite’
WINDOWPATH ‘2’
WORKON_HOME ‘/home/tony/.envs’
XAUTHORITY ‘/run/user/1000/gdm/Xauthority’
XDG_CONFIG_DIRS ‘/etc/xdg/xdg-ubuntu:/etc/xdg’
XDG_CURRENT_DESKTOP ‘ubuntu:GNOME’
XDG_DATA_DIRS ‘/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop’
XDG_MENU_PREFIX ‘gnome-’
XDG_RUNTIME_DIR ‘/run/user/1000’
XDG_SESSION_CLASS ‘user’
XDG_SESSION_DESKTOP ‘ubuntu’
XDG_SESSION_TYPE ‘x11’
XMODIFIERS ‘@im=ibus’
_ ‘/home/tony/.envs/GarageSaleWebSite/bin/python’
wsgi.errors <_io.TextIOWrapper name=’’ mode=‘w’ encoding=‘utf-8’>
wsgi.file_wrapper <class ‘wsgiref.util.FileWrapper’>
wsgi.input <django.core.handlers.wsgi.LimitedStream object at 0x74c446308550>
wsgi.multiprocess False
wsgi.multithread True
wsgi.run_once False
wsgi.url_scheme ‘http’
wsgi.version (1, 0)

Settings

Using settings module GarageSale.settings

Setting Value
ABSOLUTE_URL_OVERRIDES {}
ADMINS [(‘Tony Flury’, ‘anthony.flury@btinternet.com’)]
ALLOWED_HOSTS [‘192.168.1.76’, ‘127.0.0.1’]
APPEND_SLASH True
APPS_SETTINGS {‘user_management’: {‘EMAIL_SENDER’: ‘BranthamGarageSale@gmail.com’, ‘SITE_NAME’: ‘Brantham Garage Sale v2’}}
AUTHENTICATION_BACKENDS [‘django.contrib.auth.backends.ModelBackend’]
AUTH_PASSWORD_VALIDATORS ‘********************’
AUTH_USER_MODEL ‘user_management.UserExtended’
BASE_DIR PosixPath(‘/home/tony/Development/GarageSale’)
CACHES {‘default’: {‘BACKEND’: ‘django.core.cache.backends.locmem.LocMemCache’}}
CACHE_MIDDLEWARE_ALIAS ‘default’
CACHE_MIDDLEWARE_KEY_PREFIX ‘********************’
CACHE_MIDDLEWARE_SECONDS 600
CSRF_COOKIE_AGE 31449600
CSRF_COOKIE_DOMAIN None
CSRF_COOKIE_HTTPONLY False
CSRF_COOKIE_NAME ‘csrftoken’
CSRF_COOKIE_PATH ‘/’
CSRF_COOKIE_SAMESITE ‘Lax’
CSRF_COOKIE_SECURE False
CSRF_FAILURE_VIEW ‘django.views.csrf.csrf_failure’
CSRF_HEADER_NAME ‘HTTP_X_CSRFTOKEN’
CSRF_TRUSTED_ORIGINS
CSRF_USE_SESSIONS False
DATABASES {‘default’: {‘ATOMIC_REQUESTS’: False, ‘AUTOCOMMIT’: True, ‘CONN_MAX_AGE’: 0, ‘ENGINE’: ‘django.db.backends.postgresql’, ‘HOST’: ‘localhost’, ‘NAME’: ‘garagesale2’, ‘OPTIONS’: {}, ‘PASSWORD’: ‘********************’, ‘PORT’: ‘5432’, ‘TEST’: {‘CHARSET’: None, ‘COLLATION’: None, ‘MIGRATE’: True, ‘MIRROR’: None, ‘NAME’: ‘test_garagesale’}, ‘TIME_ZONE’: None, ‘USER’: ‘garagesaleweb’}}
DATABASE_ROUTERS
DATA_UPLOAD_MAX_MEMORY_SIZE 2621440
DATA_UPLOAD_MAX_NUMBER_FIELDS 1000
DATETIME_FORMAT ‘N j, Y, P’
DATETIME_INPUT_FORMATS [‘%Y-%m-%d %H:%M:%S’, ‘%Y-%m-%d %H:%M:%S.%f’, ‘%Y-%m-%d %H:%M’, ‘%m/%d/%Y %H:%M:%S’, ‘%m/%d/%Y %H:%M:%S.%f’, ‘%m/%d/%Y %H:%M’, ‘%m/%d/%y %H:%M:%S’, ‘%m/%d/%y %H:%M:%S.%f’, ‘%m/%d/%y %H:%M’]
DATE_FORMAT ‘N j, Y’
DATE_INPUT_FORMATS [‘%Y-%m-%d’, ‘%m/%d/%Y’, ‘%m/%d/%y’, ‘%b %d %Y’, ‘%b %d, %Y’, ‘%d %b %Y’, ‘%d %b, %Y’, ‘%B %d %Y’, ‘%B %d, %Y’, ‘%d %B %Y’, ‘%d %B, %Y’]
DEBUG True
DEBUG_PROPAGATE_EXCEPTIONS False
DEBUG_TOOLBAR_FILTER_URL (‘mail_toolbar_debug’,)
DEBUG_TOOLBAR_PANELS [‘debug_toolbar.panels.history.HistoryPanel’, ‘debug_toolbar.panels.versions.VersionsPanel’, ‘debug_toolbar.panels.timer.TimerPanel’, ‘debug_toolbar.panels.settings.SettingsPanel’, ‘debug_toolbar.panels.headers.HeadersPanel’, ‘debug_toolbar.panels.request.RequestPanel’, ‘debug_toolbar.panels.sql.SQLPanel’, ‘debug_toolbar.panels.staticfiles.StaticFilesPanel’, ‘debug_toolbar.panels.templates.TemplatesPanel’, ‘debug_toolbar.panels.cache.CachePanel’, ‘debug_toolbar.panels.signals.SignalsPanel’, ‘debug_toolbar.panels.redirects.RedirectsPanel’, ‘debug_toolbar.panels.profiling.ProfilingPanel’, ‘mail_panel.panels.MailToolbarPanel’]
DECIMAL_SEPARATOR ‘.’
DEFAULT_AUTO_FIELD ‘django.db.models.AutoField’
DEFAULT_CHARSET ‘utf-8’
DEFAULT_EXCEPTION_REPORTER ‘django.views.debug.ExceptionReporter’
DEFAULT_EXCEPTION_REPORTER_FILTER ‘django.views.debug.SafeExceptionReporterFilter’
DEFAULT_FILE_STORAGE ‘django.core.files.storage.FileSystemStorage’
DEFAULT_FROM_EMAIL ‘webmaster@localhost’
DEFAULT_INDEX_TABLESPACE ‘’
DEFAULT_TABLESPACE ‘’
DISALLOWED_USER_AGENTS
EMAIL_BACKEND ‘mail_panel.backend.MailToolbarBackend’
EMAIL_HOST ‘localhost’
EMAIL_HOST_PASSWORD ‘********************’
EMAIL_HOST_USER ‘’
EMAIL_PORT 25
EMAIL_SSL_CERTFILE None
EMAIL_SSL_KEYFILE ‘********************’
EMAIL_SUBJECT_PREFIX '[Django] ’
EMAIL_TIMEOUT None
EMAIL_USE_LOCALTIME False
EMAIL_USE_SSL False
EMAIL_USE_TLS False
FILE_UPLOAD_DIRECTORY_PERMISSIONS None
FILE_UPLOAD_HANDLERS [‘django.core.files.uploadhandler.MemoryFileUploadHandler’, ‘django.core.files.uploadhandler.TemporaryFileUploadHandler’]
FILE_UPLOAD_MAX_MEMORY_SIZE 2621440
FILE_UPLOAD_PERMISSIONS 420
FILE_UPLOAD_TEMP_DIR None
FIRST_DAY_OF_WEEK 0
FIXTURE_DIRS
FORCE_SCRIPT_NAME None
FORMAT_MODULE_PATH None
FORM_RENDERER ‘django.forms.renderers.DjangoTemplates’
IGNORABLE_404_URLS
INSTALLED_APPS [‘team_pages.apps.TeamPagesConfig’, ‘GarageSale.apps.GarageSaleConfig’, ‘Location.apps.LocationConfig’, ‘Sponsors.apps.SponsorsConfig’, ‘user_management.apps.user_managementConfig’, ‘News.apps.NewsConfig’, ‘django.forms’, ‘django.contrib.admin’, ‘django.contrib.auth’, ‘django.contrib.contenttypes’, ‘django.contrib.sessions’, ‘django.contrib.messages’, ‘django.contrib.staticfiles’, ‘django_quill’, ‘debug_toolbar’, ‘mail_panel’]
INTERNAL_IPS [‘192.168.1.76’, ‘127.0.0.1’]
LANGUAGES [(‘af’, ‘Afrikaans’), (‘ar’, ‘Arabic’), (‘ar-dz’, ‘Algerian Arabic’), (‘ast’, ‘Asturian’), (‘az’, ‘Azerbaijani’), (‘bg’, ‘Bulgarian’), (‘be’, ‘Belarusian’), (‘bn’, ‘Bengali’), (‘br’, ‘Breton’), (‘bs’, ‘Bosnian’), (‘ca’, ‘Catalan’), (‘cs’, ‘Czech’), (‘cy’, ‘Welsh’), (‘da’, ‘Danish’), (‘de’, ‘German’), (‘dsb’, ‘Lower Sorbian’), (‘el’, ‘Greek’), (‘en’, ‘English’), (‘en-au’, ‘Australian English’), (‘en-gb’, ‘British English’), (‘eo’, ‘Esperanto’), (‘es’, ‘Spanish’), (‘es-ar’, ‘Argentinian Spanish’), (‘es-co’, ‘Colombian Spanish’), (‘es-mx’, ‘Mexican Spanish’), (‘es-ni’, ‘Nicaraguan Spanish’), (‘es-ve’, ‘Venezuelan Spanish’), (‘et’, ‘Estonian’), (‘eu’, ‘Basque’), (‘fa’, ‘Persian’), (‘fi’, ‘Finnish’), (‘fr’, ‘French’), (‘fy’, ‘Frisian’), (‘ga’, ‘Irish’), (‘gd’, ‘Scottish Gaelic’), (‘gl’, ‘Galician’), (‘he’, ‘Hebrew’), (‘hi’, ‘Hindi’), (‘hr’, ‘Croatian’), (‘hsb’, ‘Upper Sorbian’), (‘hu’, ‘Hungarian’), (‘hy’, ‘Armenian’), (‘ia’, ‘Interlingua’), (‘id’, ‘Indonesian’), (‘ig’, ‘Igbo’), (‘io’, ‘Ido’), (‘is’, ‘Icelandic’), (‘it’, ‘Italian’), (‘ja’, ‘Japanese’), (‘ka’, ‘Georgian’), (‘kab’, ‘Kabyle’), (‘kk’, ‘Kazakh’), (‘km’, ‘Khmer’), (‘kn’, ‘Kannada’), (‘ko’, ‘Korean’), (‘ky’, ‘Kyrgyz’), (‘lb’, ‘Luxembourgish’), (‘lt’, ‘Lithuanian’), (‘lv’, ‘Latvian’), (‘mk’, ‘Macedonian’), (‘ml’, ‘Malayalam’), (‘mn’, ‘Mongolian’), (‘mr’, ‘Marathi’), (‘ms’, ‘Malay’), (‘my’, ‘Burmese’), (‘nb’, ‘Norwegian Bokmål’), (‘ne’, ‘Nepali’), (‘nl’, ‘Dutch’), (‘nn’, ‘Norwegian Nynorsk’), (‘os’, ‘Ossetic’), (‘pa’, ‘Punjabi’), (‘pl’, ‘Polish’), (‘pt’, ‘Portuguese’), (‘pt-br’, ‘Brazilian Portuguese’), (‘ro’, ‘Romanian’), (‘ru’, ‘Russian’), (‘sk’, ‘Slovak’), (‘sl’, ‘Slovenian’), (‘sq’, ‘Albanian’), (‘sr’, ‘Serbian’), (‘sr-latn’, ‘Serbian Latin’), (‘sv’, ‘Swedish’), (‘sw’, ‘Swahili’), (‘ta’, ‘Tamil’), (‘te’, ‘Telugu’), (‘tg’, ‘Tajik’), (‘th’, ‘Thai’), (‘tk’, ‘Turkmen’), (‘tr’, ‘Turkish’), (‘tt’, ‘Tatar’), (‘udm’, ‘Udmurt’), (‘uk’, ‘Ukrainian’), (‘ur’, ‘Urdu’), (‘uz’, ‘Uzbek’), (‘vi’, ‘Vietnamese’), (‘zh-hans’, ‘Simplified Chinese’), (‘zh-hant’, ‘Traditional Chinese’)]
LANGUAGES_BIDI [‘he’, ‘ar’, ‘ar-dz’, ‘fa’, ‘ur’]
LANGUAGE_CODE ‘en-us’
LANGUAGE_COOKIE_AGE None
LANGUAGE_COOKIE_DOMAIN None
LANGUAGE_COOKIE_HTTPONLY False
LANGUAGE_COOKIE_NAME ‘django_language’
LANGUAGE_COOKIE_PATH ‘/’
LANGUAGE_COOKIE_SAMESITE None
LANGUAGE_COOKIE_SECURE False
LOCALE_PATHS
LOGGING {}
LOGGING_CONFIG ‘logging.config.dictConfig’
LOGIN_REDIRECT_URL ‘/accounts/profile/’
LOGIN_URL ‘/accounts/login/’
LOGOUT_REDIRECT_URL None
MANAGERS
MEDIA_ROOT ‘media’
MEDIA_URL ‘/media/’
MESSAGE_STORAGE ‘django.contrib.messages.storage.fallback.FallbackStorage’
MIDDLEWARE [‘debug_toolbar.middleware.DebugToolbarMiddleware’, ‘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’, ‘GarageSale.middleware.event.CurrentEvent’]
MIGRATION_MODULES {}
MONTH_DAY_FORMAT ‘F j’
NUMBER_GROUPING 0
PASSWORD_HASHERS ‘********************’
PASSWORD_RESET_TIMEOUT ‘********************’
PREPEND_WWW False
ROOT_URLCONF ‘GarageSale.urls’
SECRET_KEY ‘********************’
SECURE_CONTENT_TYPE_NOSNIFF True
SECURE_CROSS_ORIGIN_OPENER_POLICY ‘same-origin’
SECURE_HSTS_INCLUDE_SUBDOMAINS False
SECURE_HSTS_PRELOAD False
SECURE_HSTS_SECONDS 0
SECURE_PROXY_SSL_HEADER None
SECURE_REDIRECT_EXEMPT
SECURE_REFERRER_POLICY ‘same-origin’
SECURE_SSL_HOST None
SECURE_SSL_REDIRECT False
SERVER_EMAIL ‘root@localhost’
SESSION_CACHE_ALIAS ‘default’
SESSION_COOKIE_AGE 31536000
SESSION_COOKIE_DOMAIN None
SESSION_COOKIE_HTTPONLY True
SESSION_COOKIE_NAME ‘sessionid’
SESSION_COOKIE_PATH ‘/’
SESSION_COOKIE_SAMESITE ‘Lax’
SESSION_COOKIE_SECURE False
SESSION_ENGINE ‘django.contrib.sessions.backends.db’
SESSION_EXPIRE_AT_BROWSER_CLOSE False
SESSION_FILE_PATH None
SESSION_SAVE_EVERY_REQUEST False
SESSION_SERIALIZER ‘django.contrib.sessions.serializers.JSONSerializer’
SETTINGS_MODULE ‘GarageSale.settings’
SHORT_DATETIME_FORMAT ‘m/d/Y P’
SHORT_DATE_FORMAT ‘m/d/Y’
SIGNING_BACKEND ‘django.core.signing.TimestampSigner’
SILENCED_SYSTEM_CHECKS
STATICFILES_DIRS
STATICFILES_FINDERS [‘django.contrib.staticfiles.finders.FileSystemFinder’, ‘django.contrib.staticfiles.finders.AppDirectoriesFinder’]
STATICFILES_STORAGE ‘django.contrib.staticfiles.storage.StaticFilesStorage’
STATIC_ROOT ‘static’
STATIC_URL ‘/static/’
TEMPLATES [{‘APP_DIRS’: True, ‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’, ‘DIRS’: , ‘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’, ‘django.template.context_processors.media’, ‘GarageSale.middleware.context_processors.test_server’], ‘libraries’: {‘event_data_tags’: ‘GarageSale.templatetags.garage_sale_data’, ‘newsletter_tags’: ‘News.templatetags.extras’, ‘sponsor_tags’: ‘Sponsors.templatetags.extras’, ‘team_page_tags’: ‘team_pages.templatetags.team_page_tags’, ‘user_management_tags’: ‘user_management.templatetags.extras’}}}]
TEST_NON_SERIALIZED_APPS
TEST_RUNNER ‘django.test.runner.DiscoverRunner’
TEST_SERVER True
THOUSAND_SEPARATOR ‘,’
TIME_FORMAT ‘P’
TIME_INPUT_FORMATS [‘%H:%M:%S’, ‘%H:%M:%S.%f’, ‘%H:%M’]
TIME_ZONE ‘UTC’
USE_DEPRECATED_PYTZ False
USE_I18N True
USE_L10N True
USE_THOUSAND_SEPARATOR False
USE_TZ False
USE_X_FORWARDED_HOST False
USE_X_FORWARDED_PORT False
WSGI_APPLICATION ‘GarageSale.wsgi.application’
X_FRAME_OPTIONS ‘DENY’
YEAR_MONTH_FORMAT ‘F Y’

You’re seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard page generated by the handler for this status code.

DJDT

Fair enough.

(Side note: It’s usually more helpful to post the traceback from the server console than the error page from the browser, but I think this is good enough for now.)

Looking at the Django docs for set_expiry in version 4.0:

Note that datetime and timedelta values are only serializable if you are using the PickleSerializer.

This means that to use this parameter with this version of Django, you need to change your serializer for the sessions. (According to the docs, directly saving a datetime value in the session using the JSON serializer became available in 4.1.)

Another side note, I guess my first question is when are you trying to set this? If you’re setting this in every view, or in multiple views, or in custom middleware, then it’s going to be recalculated and updated on each request.

Ken.
Thank you - you highlighted the issue i was having - using Django 4.06 but reading the Django 5 docs (in other words PEBKAC).

I will upgrade to 4.1 initially for this feature.

I am only trying to set it like this in one view - and it is a view that is only accessed when the previous session has expired