我在django 1.8和mysql 5.7中编写django应用程序。
以下是我写的模型:
class People(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField()
create_time = models.DateTimeField()
class Meta:
db_table = "people"
上面的模型创建了下表:
mysql> desc people;
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| create_time | datetime(6) | NO | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
这里Django用微秒创建日期时间字段
日期时间(6)
但我想要没有微秒的日期时间字段
日期时间
我有另一个应用程序,它也使用相同的数据库,而带有微秒的datetime字段对我来说是一个问题。
答案 0 :(得分:5)
这是非常有趣的问题。我查看了源代码,这是设置datetime
小数秒的原因。以下代码段来自文件django/db/backends/mysql/base.py
:
class DatabaseWrapper(BaseDatabaseWrapper):
vendor = 'mysql'
# This dictionary maps Field objects to their associated MySQL column
# types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
_data_types = {
'AutoField': 'integer AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',
}
@cached_property
def data_types(self):
if self.features.supports_microsecond_precision:
return dict(self._data_types, DateTimeField='datetime(6)', TimeField='time(6)')
else:
return self._data_types
# ... further class methods
在方法data_types
中,if条件检查MySQL版本。方法supports_microsecond_precision
来自文件django/db/backends/mysql/features.py
:
class DatabaseFeatures(BaseDatabaseFeatures):
# ... properties and methods
def supports_microsecond_precision(self):
# See https://github.com/farcepest/MySQLdb1/issues/24 for the reason
# about requiring MySQLdb 1.2.5
return self.connection.mysql_version >= (5, 6, 4) and Database.version_info >= (1, 2, 5)
因此,当您使用MySQL 5.6.4或更高版本时,字段DateTimeField
将映射到datetime(6)
。
我找不到任何由Django给出的调整这个的可能性,所以结束了猴子补丁:
from django.db.backends.mysql.base import DatabaseWrapper
DatabaseWrapper.data_types = DatabaseWrapper._data_types
将上述代码放在最适合您需求的位置,无论是models.py
还是__init__.py
,还是其他一些文件。
运行迁移时,即使您使用的是MySQL 5.7,Django也会为datetime
创建列datetime(6)
而不是DateTimeField
。
答案 1 :(得分:0)
这answer给了我一个主意。如果您尝试手动更改迁移,该怎么办?
首先运行python manage.py makemigrations
然后在您的应用的子目录0001_initial.py
中编辑文件migrations
(或其他名称):
class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name = 'People'
fields = [
# the fields
# ... in this part comment or delete create_time
],
),
migrations.RunSQL(
"ALTER TABLE people ADD COLUMN create_time datetime(0)",
reverse_sql="ALTER TABLE people DROP COLUMN create_time",
state_operations=[
migrations.AddField(
model_name='people',
name='create_time',
fields= models.DateTimeField(),
)
]
)
]
这只是一个例子。您可以尝试不同的选项并查看:
python manage.py sqlmigrations yourapp 0001
SQL输出是什么。而不是yourapp和0001提供应用程序的名称和迁移的数量。
以下是关于小数秒时间值的官方文档的link。
编辑:我用MySQL 5.7测试了上面的代码,它按预期工作。也许它可以帮助别人。如果您遇到一些错误,请检查您是否已安装mysqlclient
和sqlparse
。