本文适用于 python3Django (1.10.5)

在一个app的model中,为 Field 设定 default 关键字参数后,由Django生成的创建相应table的sql语句中,并没有如愿地包含default描述。

比如,

在app的model.py文件中包含:

1
2
class Test(models.Model):
price = models.IntegerField(default=0)

运行 ./manage.py makemigrations && ./manage.py sqlmigrate ... 后,Django 生成下列 SQL:

1
2
3
4
CREATE TABLE `test` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`price` integer NOT NULL
);

解决方案,改动django源码:

以下内容是针对于用mysql时的修改

修改 python3.6/site-packages/django/db/backends/base/schema.py 中的函数 column_sql :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...

# Primary key/unique outputs
if field.primary_key:
sql += " PRIMARY KEY"
elif field.unique:
sql += " UNIQUE"

# 添加以下代码
# Add Following
if hasattr(field, "mysql_now") and field.mysql_now is True:
sql += " DEFAULT CURRENT_TIMESTAMP"
if field.default != models.fields.NOT_PROVIDED:
if isinstance(field.default, (int, float)):
sql += " DEFAULT " + field.default.__str__()
if isinstance(field.default, bool):
sql += " DEFAULT 1" if field.default else " DEFAULT 0"
if isinstance(field.default, str):
sql += " DEFAULT '{}'".format(field.default)

...

上输代码还没有完全解决 datetime 类型的 DEFAULT CURRENT_TIMESTAMP ,还需要创建一个新的 Field 类:

1
2
3
4
5
6
7
8
9
class DateTimeDateField(models.DateField):
"""DateTimeDateField use 'datetime' instead of 'date'"""

def __init__(self, *arg, **karg):
super(DateTimeDateField, self).__init__(*arg, **karg)
self.mysql_now = karg.get("auto_now", False)

def db_type(self, connection):
return "datetime"

新类型的使用方式:

1
2
3
4
class Test(models.Model):
...
testcolumn = DateTimeDateField(auto_now=True)
...

然后, default 关键字参数就能如愿生成到 mysql 中的列描述中了:

比如,

model.py 中包含:

1
2
3
4
5
6
7
8
9
10
11
class User(models.Model):
"""Model about user foundation"""

account = FixedCharField(max_length=11, verbose_name="账号")
name = models.CharField(max_length=128, default="无名", null=True, verbose_name="名字")
pre_login_time = DateTimeDateField(auto_now=True, verbose_name="上次登录时间")
signup_time = DateTimeDateField(auto_now=True, verbose_name="登录时间")
token = models.CharField(max_length=64, null=True)

def __str__(self):
return "{}-{}".format(self.account, self.name)

而生成的sql语句为:

1
CREATE TABLE `user` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `account` char(11) NOT NULL, `name` varchar(128) NULL DEFAULT '无名', `pre_login_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `signup_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `token` varchar(64) NULL);