关于python:Django ORM,将无日期时间作为0插入MySQL

Django ORM, Insert None datetime as 0 into MySQL

我有一个MySQL数据库,除了Django,其他应用程序也在使用它。该应用程序使用'0000-00-00 00:00:00'作为日期时间的默认值。

django(v1.5.5)在读取数据库时将'0000-00-00 00:00:00'日期时间解释为None,在写入数据库时将None解释为NULL。这会导致错误,因为数据库将字段定义为NOT NULL

手动设置:

1
model.datetime = '0000-00-00 00:00:00'

不起作用,因为Django觉得这是一个无效的日期。

如何创建一个自定义日期时间字段,该字段将None作为'0000-00-00 00:00:00'插入?


基于seppo的解决方案(由于缺少connection.ops.value_to_db_datetime,因此在django 1.9.4中不起作用),我最终使用了一个自定义的datetime字段,如下所示:

1
2
3
4
5
6
7
8
from django.db import models

class ZeroDateTimeField(models.DateTimeField):
    def get_db_prep_value(self, value, connection, prepared=False):
        value = super( ZeroDateTimeField, self ).get_db_prep_value( value, connection, prepared )
        if value is None:
            return "0000-00-00 00:00:00"
        return value

然后在模型中使用zerodatetimefield,而不是datetimefield。

像个魔咒一样工作,我不得不告诉客户修复他的mysql db;-)

编辑:我最终重写了构造函数来设置null=true和blank=true,以便于使用自动生成的模型。因为这可能对某些人有用,所以这里是(这是可选的和有问题的):

1
2
3
4
def __init__(self, verbose_name=None, name=None, auto_now=False, auto_now_add=False, **kwargs):
    kwargs['null'] = True
    kwargs['blank'] = True
    super( ZeroDateTimeField, self ).__init__(verbose_name, name, auto_now, auto_now_add, **kwargs)

创建自定义DateTimeField并覆盖get_db_prep_value。该方法是从django源复制粘贴的,并添加了一个用于处理None的案例。该值应该以特定于数据库的方式转换,因此这有点不太合理,但只要数据库接受0000-00-00 00:00:00作为日期时间,它就可以工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.db import models

class ZeroDateTimeField(models.DateTimeField):
    def get_db_prep_value(self, value, connection, prepared=False):
        # Casts datetimes into the format expected by the backend
        if not prepared:
            value = self.get_prep_value(value)

        # Use zeroed datetime instead of NULL
        if value is None:
            return "0000-00-00 00:00:00"

        else:
            return connection.ops.value_to_db_datetime(value)

编辑:此答案是为Django 1.5编写的,尚未测试对其他版本的支持。


default参数添加到datetime字段时会发生什么?

江户十一〔一〕号

我认为如果MySQL接受它,Django也应该接受。