Importing DateTime Error Message:
RuntimeWarning: DateTimeField Entry.date received a naive datetime (2020-07-20 09:23:19.881763) while time zone support is active.
RuntimeWarning)
Is there a way a user can select the datetime they are in or at least import the data with +00 added? Currently, I can't seem to be able to import once I add the datetime field.
Right now I'm trying this issue solution
resources.py
class TzDateTimeWidget(DateTimeWidget):
def render(self, value, obj=None):
if settings.USE_TZ:
value = localtime(value)
return super(TzDateTimeWidget, self).render(value)
class EntryResource(resources.ModelResource):
date = fields.Field(
column_name='date',
attribute='datetime',
widget=TzDateTimeWidget(format='"%Y-%m-%d %H:%M:%S"'))
class Meta:
model = Entry
fields = ('date', 'entry_type', 'amount', 'price', 'fee', 'reg_fee', 'id',)
import_order = fields
skip_unchanged = False
report_skipped = True
csv file
2020-07-17 7:42:39,,40,14.56,0,Entry,0
2020-07-17 7:47:16,,40,14.78,0,Entry,0
The issue is that the datetime in your csv file is not Timezone aware. There are a few ways to solve this.
You don't need timezone information in the csv if you know that the supplied date is always going to be in your timezone, because it will be converted during import and have the correct timezone.
If the supplied timestamps are timezone aware, then you can handle this during import:
csv:
2020-07-20 00:00:00+03:00,40,14.56,0,Entry,0
Widget:
class TzDateTimeWidget(widgets.DateTimeWidget):
def clean(self, value, row=None, *args, **kwargs):
if not value:
return None
if isinstance(value, datetime):
return value
for format in self.formats:
try:
if settings.USE_TZ:
dt = parse_datetime(value)
return dt
except (ValueError, TypeError):
continue
raise ValueError("Enter a valid date/time.")
If your users can be in any timezone, but it is not possible to encode tz in the csv, then you can store the User's timezone (e.g. in a custom User model instance), and apply the conversion for the user during import.
A simplified version of this would be:
class UserDateTimeWidget(widgets.DateTimeWidget):
def __init__(self, user_tz_dict):
"""pass in a dict mapping user_id to timezone"""
super().__init__()
self.user_dict = user_tz_dict
def clean(self, value, row=None, *args, **kwargs):
dt = super().clean(value, row, args, kwargs)
# the row will need to contain a reference to the user id
user_id = row.get("user_id")
user_tz = self.user_dict.get(user_id)
return make_aware(dt, timezone=user_tz)
It's important to note that this relies on the csv timestamp being in a consistent standard, such as UTC.
Note that there are other ways you could achieve the above, such as overriding the Model save()
method to apply the User's timezone at the point of saving the instance. Obviously you have to link the User to the imported object.
As a side note, the TzDateTimeWidget
you reference will only format the date in the defined timezone when the data is exported. This functionality is already present in DateTimeWidget
.