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

标签 django django-forms django-admin django-orm 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 及更高版本支持小数秒作为输入格式: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)

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

并修改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

第 167 行
supports_microsecond_precision = True

第 214 行
compiler_module = "django.db.backends.mysql564.compiler"

第 357 行
return six.text_type(value) #value.replace(microsecond=0)

第368行
return six.text_type(value) #value.replace(microsecond=0)

第373行
return [first, second] #return [first.replace(microsecond=0), second.replace(microsecond=0)]

然后我在 settings.py 中激活了我的新后端:
'ENGINE': 'django.db.backends.mysql564',

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

Sequel Pro

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

Django admin

我在这里缺少什么?
  • 为什么不返回 DateTimeFractionField 值?
  • 有没有更好(更简单)的方法来实现支持分数的日期时间字段?

  • 我知道还有其他数据库的支持分数。但我喜欢使用 MySQL 并获得更接近修复的票证。

    更新:

    这不是(仅)形式,从 de db 获取日期时间对象失败。
    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
    

    最佳答案

    我已经成功地尝试过这个,但我的方法完全不同:
    我将信息拆分为 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()
    

    然后我在类中设置一个属性以返回带有微秒和区域信息感知的 UTC(因为我的数据库不支持 zoneinfo)
        @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
    

    关于django - 如何创建一个 Django 自定义字段来存储 MYSQL DATETIME(6) 并在 Django/MySQL 中启用小数秒(毫秒和或微秒)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17846504/

    相关文章:

    django - 如何向 Django 模型添加额外数据以在模板中显示?

    django - ValueError - 无法创建消火栓,因为数据未验证

    python - 我应该在哪个文件中定义为模型创建的 ModelForm?

    python - 如何从预填充对象的表单中排除字段

    python - Django Admin 修改模型继承

    Django - {% load url from future %} 产生错误 "' url' 不是有效的标签库”

    django - 如何从Django中删除模型?

    python - 在 Django 中获取多对多关系中的第一个项目

    django - 反向 django 自定义管理站点 URL

    django - 为什么我无法在 ModelForm 的 save() 函数中设置 OneToOneField?