SQLite3没有捕获太长的用户名

时间:2013-01-31 23:25:56

标签: django sqlite

我最近修改了我的Django项目的设置,因为它在我运行测试而不是PostgreSQL时使用SQLite3,这样我的测试运行得更快。但是,一旦我这样做,我的一个负面单元测试检查验证Django如果我尝试创建一个用户名超过30个字符的用户就会失败。直到这个时候,测试一直都过去了。

如果我使用PostgreSQL运行以下测试,则会引发异常(特别是DatabaseError)并且测试通过。但是,如果我使用SQLite3,则不会引发异常并且测试失败。我仔细检查了SQLite3 auth_user架构,并确认用户名是varchar(30)字段。还有其他人经历过这个吗?感谢。

from django.test import TestCase
from django.contrib.auth.models import User

class SimpleTest(TestCase):
    def test_simple(self):
        exception_raised = True  # Exception should be raised since username > 30 chars
        try:
            user = User.objects.create_user(username='testusertestusertestusertestuser')
        except Exception as e:
            exception_raised = False
        assert not exception_raised, "Exception wasn't raised"

2 个答案:

答案 0 :(得分:1)

除了Zuko的答案之外,我还会质疑你的单元测试可能没有做正确的事情。

模型验证在保存之前发生似乎是一种常见的误解。请参阅Model validation的文档。

您正在做的是期望您的模型字段的max_length参数得到兑现,而无需通过验证功能。当您使用ModelForms时,表单将确保调用模型验证,您将获得ValidationError

这同样适用于其他约束,例如is_blank类型的CharField选项。据我所知,此验证只能在Python域中进行,因为没有可用的约束,您可以在数据库级别应用以检查字段是否为空。

StackOverflow上有很多其他问题与此问题相关,这将解释您如何在所有情况下强制进行验证,例如this answer

另外,让您的单元测试调用full_clean()实例方法来检查是否已满足所有验证约束。

答案 1 :(得分:0)

我认为原因是sqlite3将所有varchar数据类型转换为引擎盖下的文本数据类型。这就是DBMS不会捕获任何超出限制的值的原因。在这方面文档有点不清楚,但我在文档之前和之后遇到了这个问题,这是我能想到的最好的答案。所以基本上,

CREATE TABLE A(name varchar(30))

最终会与以下内容完全相同:

CREATE TABLE A(name text)

查看此处的文档(第2.2节):http://www.sqlite.org/datatype3.html

您可以做的测试,看看这只是DBMS的功能:

sqlite> create table A(name varchar(2));
sqlite> insert into A values("hello world");
sqlite> select * from A;
hello world

如您所见,没有错误,也没有截断。

希望有所帮助,