如何创建一个Django自定义字段来存储MYSQL DATETIME(6)并在Django/MySQL中启用小数秒(毫秒和/或微秒)?

all*_*aps 5 django django-forms django-orm django-admin django-database

MySQL 5.6.4及更高版本扩展了对TIME,DATETIME和TIMESTAMP值的小数秒支持,精度高达微秒(6位):http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds html的

Django 1.5及以上支持小数秒作为imputformat:https://docs.djangoproject.com/en/1.5/ref/settings/#datetime-input-formats

但DATETIME(6)字段尚未在Django中实现. https://code.djangoproject.com/ticket/19716

我决定编写一个自定义的DateTimeFractionField.它是具有DATETIME([1-6])db_type的标准DateTimeField.'precicion'用于设置毫秒,微秒或任何其他分数精度.

class DateTimeFractionField(models.DateTimeField):
    description = "Datetimefield with fraction second."

    def __init__(self, precision, *args, **kwargs):
        self.precision = precision
        super(DateTimeFractionField, self).__init__(*args, **kwargs)

    def db_type(self, connection):
        return 'DATETIME(%s)' % self.precision


class MyModel(models.Model):
    dt_micros  = DateTimeFractionField(6)
    dt_millis = DateTimeFractionField(3)
    dt = models.DateTimeField()

    def __unicode__(self):
        return "%s - %s" %(self.dt_micros, self.dt_millis)
Run Code Online (Sandbox Code Playgroud)

mysql后端负责用0替换毫秒.Django文档建议编写我自己的后端.https://docs.djangoproject.com/en/1.5/ref/settings/#engine

我砍了:

$ cd /path/to/site-packages/django/db/backends/
$ cp -r mysql mysql564
Run Code Online (Sandbox Code Playgroud)

并修改了mysql564/base.py:

42:45行

from django.db.backends.mysql564.client import DatabaseClient
from django.db.backends.mysql564.creation import DatabaseCreation
from django.db.backends.mysql564.introspection import DatabaseIntrospection
from django.db.backends.mysql564.validation import DatabaseValidation
Run Code Online (Sandbox Code Playgroud)

第167行

supports_microsecond_precision = True
Run Code Online (Sandbox Code Playgroud)

第214行

compiler_module = "django.db.backends.mysql564.compiler"
Run Code Online (Sandbox Code Playgroud)

357行

return six.text_type(value) #value.replace(microsecond=0)
Run Code Online (Sandbox Code Playgroud)

368行

return six.text_type(value) #value.replace(microsecond=0)
Run Code Online (Sandbox Code Playgroud)

第373行

return [first, second] #return [first.replace(microsecond=0), second.replace(microsecond=0)]
Run Code Online (Sandbox Code Playgroud)

然后我在settings.py中激活了我的新后端:

'ENGINE': 'django.db.backends.mysql564',
Run Code Online (Sandbox Code Playgroud)

当我在管理员中添加并保存我的模型时,值将保存到de db!:)

续集专业

但它们不会被返回(无 - 无和空表单字段).:(

Django管理员

我在这里错过了什么?

  1. 为什么不返回DateTimeFractionField值?
  2. 是否有更好(更简单)的方法来实现支持分数的datetimefield?

我知道还有其他db支持分数.但我喜欢使用MySQL并使票更接近修复.

更新:

它不是(仅)表单,从de db获取datetime对象失败.

In [1]: from spacetime.models import MyModel

In [2]: from django.shortcuts import get_object_or_404

In [3]: get_object_or_404(MyModel, pk=1).dt
Out[3]: datetime.datetime(2013, 7, 25, 0, 22, 23)

In [4]: get_object_or_404(MyModel, pk=1).dt_millis

In [5]: get_object_or_404(MyModel, pk=1).dt_millis.__class__
Out[5]: NoneType #This should be datetime.datetime
Run Code Online (Sandbox Code Playgroud)

Anr*_*Anr 1

我已经成功地尝试了这一点,但我的方法完全不同:我将信息拆分为 DateTimeField (UTC) 和 IntegerField (微秒 = us):

from datetime                   import datetime, timedelta
import pytz

class MyModel (models.Model):
    # My model stuff and other fields here
    _UTC = models.DateTimeField ()
    _uS  = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)

然后我在类中设置一个属性以返回具有微秒和区域信息感知的 UTC(因为我的数据库不支持区域信息)

    @property
    def UTC (self): 
        utc = self._UTC
        us  = self._uS
        # add microseconds
        utc += timedelta(microseconds=us)
        return utc.replace(tzinfo=pytz.utc)
    @UTC.setter
    def UTC (self,utc):
        self._UTC = utc-timedelta(microseconds=utc.microsecond) # without microseconds
        self._uS = utc.microsecond
Run Code Online (Sandbox Code Playgroud)