Cannot import datetime field having db_default attribute (new in Django 5.0)
ipamo opened this issue · comments
Describe the bug
Trying to import datetime fields having db_default attribute produce AttributeError: 'DatabaseDefault' object has no attribute 'utcoffset'
.
To Reproduce
Steps to reproduce the behavior:
- Configure a model with field
DateTimeField(auto_now_add=True, db_default=Now())
- Try to import data to this model in the admin site
See this dedicated repository to reproduce the issue.
Versions
- Windows 10 22H2 (build 19045.3930)
- Python 3.11.5
- PostgreSQL 15.4
- Django 5.0.1
- Psycopg 3.1.17
- Django-import-export 3.3.6
Traceback
Traceback (most recent call last):
File "…\import-db-default\.venv\Lib\site-packages\import_export\resources.py", line 785, in import_row
diff = self.get_diff_class()(self, original, new)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…\import-db-default\.venv\Lib\site-packages\import_export\resources.py", line 259, in __init__
self.left = self._export_resource_fields(resource, instance)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…\import-db-default\.venv\Lib\site-packages\import_export\resources.py", line 280, in _export_resource_fields
return [
^
File "…\import-db-default\.venv\Lib\site-packages\import_export\resources.py", line 281, in <listcomp>
resource.export_field(f, instance) if instance else ""
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…\import-db-default\.venv\Lib\site-packages\import_export\resources.py", line 1066, in export_field
return field.export(obj)
^^^^^^^^^^^^^^^^^
File "…\import-db-default\.venv\Lib\site-packages\import_export\fields.py", line 148, in export
return self.widget.render(value, obj)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…\import-db-default\.venv\Lib\site-packages\import_export\widgets.py", line 266, in render
value = timezone.localtime(value)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "…\import-db-default\.venv\Lib\site-packages\django\utils\timezone.py", line 182, in localtime
if is_naive(value):
^^^^^^^^^^^^^^^
File "…\import-db-default\.venv\Lib\site-packages\django\utils\timezone.py", line 234, in is_naive
return value.utcoffset() is None
^^^^^^^^^^^^^^^
AttributeError: 'DatabaseDefault' object has no attribute 'utcoffset'
Thanks for raising. I have found that you can reproduce the same issue in the shell with:
>>> from django.db.models.functions.datetime import Now
>>> from django.utils import timezone
>>> timezone.localtime(Now())
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/matthew/.virtualenvs/django-import-export/lib/python3.11/site-packages/django/utils/timezone.py", line 182, in localtime
if is_naive(value):
^^^^^^^^^^^^^^^
File "/Users/matthew/.virtualenvs/django-import-export/lib/python3.11/site-packages/django/utils/timezone.py", line 234, in is_naive
return value.utcoffset() is None
^^^^^^^^^^^^^^^
The interface of timezone.localtime()
states that a datetime
instance is passed, therefore it's not valid to pass a Now
instance.
The issue is that the 'diff' process used to show the differences in the import uses DateTimeWidget
which is being asked to render a Now
instance (it assumes it is being passed a date). Hence it crashes. This is only occurring on the import of new objects, so I expect that the issue occurs when diffing against a 'new' instance.
I added a test here.
I don't know what the solution is at the moment.
As a workaround, you can avoid the crash during import if you set skip_diff
to True on the resource:
class BookResource(ModelResource):
class Meta:
model = Book
skip_diff = True
This means that you would not be able to see diffs on import.
Thank you very much for the explanation and workaround.
np - I'll add a fix for this when I get a chance.
I suggest that the best way to fix this would be for each widget render()
method to have a type check which checks that the value passed corresponds to the underlying type, if not then a TypeError is raised. Callers further up the stack can then catch this error and handle accordingly.