7

愚蠢的提问时间。即使我省略了定义为 NOT NULL 的列并且我不明白为什么,我似乎也能够为 Django 模型创建一个对象。这是我的模型:

class Movie(models.Model):
    name = models.CharField(max_length=256)
    length_minutes = models.IntegerField()
    rating = models.CharField(max_length=2)

    class Meta:
        db_table = 'movies'

当我运行python manage.pysql 时,我看到:

BEGIN;
CREATE TABLE "movies" (
  "id" serial NOT NULL PRIMARY KEY,
  "name" varchar(256) NOT NULL,
  "length_minutes" integer NOT NULL,
  "rating" varchar(2) NOT NULL
);
COMMIT;

此外,如果我\d movies从运行命令psql,我可以看到所有列都被指定为NOT NULL

但这是我不明白的。当我运行 Python shell 时,我可以发出以下命令,并且将创建一个带有空“名称”列的新行:

Movie.objects.create(length_minutes=120, rating='PG')

但是,如果我发出(我认为是)等效的 SQL 命令:

INSERT INTO movies(length_minutes, rating) VALUES(120, 'PG');

......我得到了我期望的错误:“错误:空值......违反了非空约束。”

为什么 Django 的 ORM 允许我创建一个缺少NOT NULLCharField 列参数的对象?它是否假设我正在使用模型验证器?如果是这样,它似乎是一个非常愚蠢和信任的 ORM。

我正在使用 Python 2.7.1、Django 1.4 和 PostgreSQL 9.1.4。

谢谢你的帮助。

4

2 回答 2

12

经过大量的在线研究和实验,我发现我上面描述的行为是正常的 Django 行为。显然,Django 默认不验证模型。此外,CharField 的默认值是空字符串。为了确保在我省略指定 NOT NULL 的 CharField 参数时 Django 引发预期的 IntegrityError,我需要在签名声明中添加“default=None”:

name = models.CharField(max_length=256, default=None)

我可以因回答自己的问题而获得荣誉吗?

于 2012-10-14T22:25:00.007 回答
2

空字符串''不是NULL,它是空字符串。''是一个完全有效的非空值。如果''不是您的应用程序可接受的值,请添加CHECK如下约束:

ALTER TABLE movies
ADD CONSTRAINT movie_name_length 
CHECK (length(name) > 0);

看起来 Django 或您的应用程序假设当您不指定名称时,您需要一个空名称'',而不是NULL. 请参阅Django 文档Field.null,这不是我所说的 ... clear ... 但似乎表明默认情况下没有任何值被视为''

于 2012-10-14T05:18:09.320 回答