I have a table whose primary key is a DateField.
For a number of reasons I have been using Django 1.7 (slightly modified for Python 3.x). In this version the admin interface for this table worked properly (for both MSSQL 2008 R2, and PostgreSQL 14 databases).
However after upgrading to Django 4.2 and 5.0 (both versions) on PostgreSQL 14, while displaying this table in the admin interface works, trying to delete a row fails in the following way.
After selecting the row to be deleted, I get the correct prompt
Are you sure?
Are you sure you want to delete the selected opd open date? All of the following objects and their related items will be deleted:
Summary
Objects
Answering the question in the affirmative, I then get the following error.
ValidationError at /hmis/admin/billing/opdopendate/
[‘“Dec. 25, 2023” value has an invalid date format. It must be in YYYY-MM-DD format.’]
Request Method: |
POST |
Request URL: |
http://127.0.0.1:8082/hmis/admin/billing/opdopendate/ |
Django Version: |
5.0 |
Exception Type: |
ValidationError |
Exception Value: |
[‘“Dec. 25, 2023” value has an invalid date format. It must be in YYYY-MM-DD format.’] |
Exception Location: |
/home/myuser/dj4/lib/python3.10/site-packages/django/db/models/fields/init.py, line 1486, in to_python |
Raised during: |
django.contrib.admin.options.changelist_view |
Python Version: |
3.10.13 |
Python Path: |
[‘/code’, ‘/usr/local/lib/python310.zip’, ‘/usr/local/lib/python3.10’, ‘/usr/local/lib/python3.10/lib-dynload’, ‘/home/myuser/dj4/lib/python3.10/site-packages’] |
Server time: |
Fri, 08 Dec 2023 09:26:09 +0545 |
The issue appears to be associated with the delete_selected_confirmation.html
template, where the hidden form field is specified as:
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}">
This template is rendered in django.contrib.admin.actions
, in the delete_selected
function by:
return TemplateResponse(
request,
modeladmin.delete_selected_confirmation_template
or [
"admin/%s/%s/delete_selected_confirmation.html"
% (app_label, opts.model_name),
"admin/%s/delete_selected_confirmation.html" % app_label,
"admin/delete_selected_confirmation.html",
],
context,
)
I would then guess that you could override this template for this operation for this model by creating your own template in your app’s template directory at the path admin/billing/opdopendate/delete_selected_confirmation.html
You should then be able to render the date any way you need to.
That was a fantastic insight, but it did take me a second to figure out how to fix it.
I copied the default template to the template location mentioned (templates\admin\<app>\<model>\
), deleted everything between the “load” tag and the “content” block, then replaced unlocalize
with date:"c"
. That changes to the ISO8601 standard per Built-in template tags and filters | Django documentation | Django.
A little testing to confirm and away I go! Thanks for the insight!
Updated code (formatted by djlint, unchanged code removed for clarity):
{% extends "admin/delete_selected_confirmation.html" %}
{% load i18n l10n admin_urls static %}
{% block content %}
{% if perms_lacking %}
...
{% elif protected %}
...
{% else %}
...
<form method="post">
{% csrf_token %}
<div>
{% for obj in queryset %}
<input type="hidden"
name="{{ action_checkbox_name }}"
value="{{ obj.pk|date:"c" }}"> {# relevant change; ISO8601 format #}
{% endfor %}
<input type="hidden" name="action" value="delete_selected">
<input type="hidden" name="post" value="yes">
<input type="submit" value="{% translate "Yes, I’m sure" %}">
<a href="#" class="button cancel-link">{% translate "No, take me back" %}</a>
</div>
</form>
{% endif %}
{% endblock content %}