2016-05-28 4 views
1

Использование mongoengine Document, когда я нахожу DateTimeField от монго, ему не хватает tzinfo. Наше приложение по правилам хочет, чтобы все даты имели tzinfo.Как применить CodecOptions к коллекции mongoengine для получения tzinfo?

Когда я спасу в монго, я знаю, что pymongo делает правильную и предсказуемую вещь по часовой стрелке; если он наивен, он сохраняется как время UTC, если он имеет часовой пояс, он преобразуется в UTC, а затем сохраняется как время UTC. Все хорошо до сих пор.

При загрузке, однако, DateTimeField всегда дает мне наивный datetime. Я знаю, что это datetime в UTC, поэтому я мог бы добавить tzinfo, если бы захотел, но мне пришлось бы делать это в десятках мест в моем приложении, и это гарантия будущих ошибок в часовом поясе, , если Я использую настраиваемый тип поля (см. пример ниже).

Ссылка: https://api.mongodb.com/python/current/examples/datetimes.html Я знаю, что pymongo поддерживает перенос tzinfo на объект по мере поступления из базы данных. Я также знаю, что я могу сделать это сам, как показывает следующий минимальный пример. DateTimeTZField добавляет tzinfo в to_python.

from datetime import datetime 

from mongoengine import connect, Document, fields 

from pytz import timezone 

def utcnowTZ(): 
    return datetime.utcnow().replace(tzinfo=timezone('UTF')) 

class DateTimeTZField(fields.DateTimeField): 
    """ 
    This seems like a hack. I would like to use CodecOptions instead 
    """ 
    def to_python(self, value): 
     converted = super(DateTimeTZField, self).to_python(value) 
     return converted.replace(tzinfo=timezone('UTC')) 

class Thing(Document): 
    dtTZ = DateTimeTZField(default=utcnowTZ) 
    dtXX = fields.DateTimeField(default=utcnowTZ) 

connect(host="mongodb://localhost/datetimewithtz") 
Thing.objects().delete() 

t1 = Thing() 
print '%r.dtXX (default): %s' % (t1, t1.dtXX) 
print '%r.dtTZ (default): %s' % (t1, t1.dtTZ) 
t1.save() 
print 'saved %r' % t1.id; print 
t1 = Thing.objects(id=t1.id).first() 
print 'reloaded %r' % t1.id 
print '%r.dtXX (loaded): %s' % (t1, t1.dtXX) 
print '%r.dtTZ (loaded): %s' % (t1, t1.dtTZ) 

Без заменяющего DateTimeField на протяжении моего приложения, есть способ использовать BSON CodecOptions сделать это применяется глобально ко всему DateTimeFields: при загрузке из базы данных, они должны иметь tzinfo прилагаются?

ответ

1

Мое понимание заключается в том, что mongoengine не поддерживает для каждой моделиcodec_options. Если это так, они должны быть частью словаря optshere.

Однако PyMongo по умолчанию использует базу данных codec_options, когда коллекция не имеет ее собственной, и вы можете установить ее вручную, указав в своем приложении, прежде чем делать какие-либо запросы к БД.

В вашем примере выше, вы должны пройти codec_options так:

with_timezone = CodecOptions() 
connect(host="mongodb://localhost/datetimewithtz", codec_options=with_timezone) 
+0

Спасибо за вдумчивый ответ, я вернусь, как только я попробовал это. Я собираюсь создать экземпляр CodecOptions (tz_aware = True), дайте мне знать, если это неправильно. – Cory