在uliweb 0.2版本以前,在定义ORM Model时,我们可以在定义某个字段时传入 nullable
, server_default
参数。nullable为True或False分别表示取值可以为null或不为null。server_default
其实是底层的sqlalchemy的一个参数,它的作用是在表示时添加DEFAULT内容。下面分别说一下。
对于nullable,如果定义为False,则在建表时,将会使用 NOT NULL信息,这样就表示你不能向这个字段添加null值。在mysql的索引中,如果值为null是不会将其内容加到索引中的。所以很多情况下,在建表时都会指明是NOT NULL。那么在0.2之前,缺省的nullable=True。在0.2版,我将其改为了False。所以这是一个很大的变化。这种变化会影响现在已经在存的应用。如果你的某个字段值已经存在为null的,将表结构修改为NOT NULL会因为无法将null转为其它的合法值而造成alter table失败。所以,为了让现存的应用还保持原来的配置,在uliweb.contrib.orm的settings.ini中添加了新的ORM的配置项: NULLABLE
. 它是一个全局的配置。当没有在定义字段时传入nullable参数时,它将起作用。因此,如果你想保持原来的方式,可以在 settings.ini 中设置它为True。
对于server_default,缺省为None,则不会生成DEFAULT信息。这里对于mysql数据库有一些限制:
- TEXT, BLOB 字段类型不支持DEFAULT
- FLOAT类型应定义为 0
- DATETIME, DATE, TIME的缺省为可以分别为:
0000-00-00 00:00:00
,0000-00-00
和00:00:00
。在处理时,仍然可以使用 date is null来查询。
对于在使用SQLAlchemy来定义server_default时,象 0这样的值,不能直接写 server_default=0
,而是要:
from sqlalchemy.sql import text
... server_default=text('0')
这样,生成的sql语句会是 : DEFAULT 0
如果是一个简单的字符串,如: server_default=''
会转为 DEFAULT ''
在ORM的配置中,也添加了这样一个全局配置, ORM/SERVER_DEFAULT
。缺省为 False。因此你可以在settings.ini中修改它。
在大多数情况下nullable和 server_default
是需要联用的。在测试中发现,如果一个字段定义为not null,但是在insert时没有给出时确的值时,如果不定义 server_default
,这时数据库会报错。经过查看mysql的文档,这是和mysql的 sql_mode
有关系的。 sql_mode
有许多的值,我查了我本地的定义是:STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
。其中第一个表示严格模式,它会当没有给出缺省值,而字段又是NOT NULL时报错。其实也可以让Mysql自动根据数据类型给出一个缺省值,可以手工修改这个 sql_mode
。因此为了减少错误,uliweb提供了 server_default
的自动生成,前提是你打开了 SERVER_DEFAULT
的开关项。当然,手工传也是可以的。
其实对于没有给值,在开发时还是很容易发现的。最主要的问题就是在修改表结构时,当我们修改了某个字段的 nullable
和 server_default
属性时,如果处理不好,会有很多不期望的值,比如一个integer类型的值可能是null,但同时又要求它not null,那么通过设置 server_default
会比较好的解决这个问题。
因此请注意这两个ORM相关的配置项
NULLABLE = False
SERVER_DEFAULT = False
第一个为了和以前的兼容,可以改为True。