django-elasticsearch-dsl-drf
django-elasticsearch-dsl-drf copied to clipboard
Strange behaviour of DictionaryProxy
Hi!
I have ES document with date field and corresponding Django model DateTimeField. However, when i'm trying to retrieve document via drf, it returns datetime.date object, not datetime.datetime, how expected.
In debug mode i found, that serializer gets field values through DictionaryProxy (utils.py):
Why it should convert datetime.datetime to datetime.date?
@Widly:
Thanks for reporting this.
It's indeed an issue, however not an easy one. There's only one date type in Elastic and that's date. It serves both, though.
Would you consider 23:30:59T00:00:00 a date or a datetime? I guess it should be possible to read the stored format (or specify it explicitly for the given field).
Any help here is appreciated.
Hi, I just found this issue too and the serialization process is not consistent between single and multiple objects. In single objects the field is serialized as a date, but in multiple objects (a list request for example) the field is serialized as a datetime.
I might be wrong, but my guess is that serializing everything as datetime would be better as it does not cut information from dates nor datetimes, however serializing everything as a date cuts some information from datetimes.
I had the same error. I made a patch / hack to add a test if the date has a timezone :
val = self.__mapping.get(item, None)
if isinstance(val, datetime.datetime) and not val.tzinfo:
val = val.date()
return val
It works but it's not a perfect solution and it might not work in your environement.
For me does not occur on list just retrieve and the first clue to the error i got was
'datetime.date' object has no attribute 'utcoffset'
In my settings.py i monkey patched like so
"""
MONKEY PATCH
"""
from django_elasticsearch_dsl_drf.utils import DictionaryProxy as OrgDictionaryProxy
import django_elasticsearch_dsl_drf.utils
import datetime
class DictionaryProxy(OrgDictionaryProxy):
"""site-packages/django_elasticsearch_dsl_drf/utils.py"""
def __getattr__(self, item):
val = self.__mapping.get(item, None)
if isinstance(val, datetime.datetime) and not val.tzinfo:
val = val.date()
return val
django_elasticsearch_dsl_drf.utils.DictionaryProxy = DictionaryProxy
I don't use date objects so i'm not really testing that.
Just remember to watch the releases and remove the patch when it gets fixed.
I hope this helps people needing to work around this.
@yleclanche, @NoelJames, @piedrahitapablo:
Thanks for your input. Could you guys, come to a consensus that will be useful for all of you? I'll see then what I can do.
Some other odd things i noticed was that in retrieve nested objects were not effect by this and, it wasn't an issue in list. IMHO I don't think having this one off behavior is helping anybody.
It would seem that to do this properly you'd need need to know the serializer field it goes into. Perhaps, there would be a better place to change the type?
Want to add that this project is very useful to me. Thank you
- I've added
... and not val.tzinfoas you suggested. - I've added the
DictionaryProxyas a property (dictionary_proxy) to theBaseDocumentViewSetso that you wouldn't have to monkey patch.
Further than that, your input is very valuable.
FYI, improvements mentioned above are released in 0.22. Feel free to add.