我想使auth_user.email
不区分大小写的唯一,可空和默认为null。以下几乎可行:
from django.db.models.signals import post_syncdb
import app.models
SQLITE_AUTH_REFORM = [
"PRAGMA writable_schema = 1;",
"""UPDATE SQLITE_MASTER SET SQL =
'CREATE TABLE auth_user (
"id" integer NOT NULL PRIMARY KEY,
"username" varchar(30) NOT NULL UNIQUE,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL,
"email" varchar(75) DEFAULT NULL,
"password" varchar(128) NOT NULL,
"is_staff" bool NOT NULL,
"is_active" bool NOT NULL,
"is_superuser" bool NOT NULL,
"last_login" datetime NOT NULL,
"date_joined" datetime NOT NULL
)' WHERE NAME = 'auth_user';""",
"PRAGMA writable_schema = 0;",
]
def post_syncdb_callback(sender, **kwargs):
from django.db import connections
from django.conf import settings
cursor = connections['default'].cursor()
if 'sqlite' in settings.DATABASES['default']['ENGINE']:
for stmt in SQLITE_AUTH_REFORM:
cursor.execute(stmt)
cursor.execute(
"CREATE UNIQUE INDEX IF NOT EXISTS auth_user_email_unique "
"ON auth_user (email COLLATE NOCASE);"
)
else: # Oracle
cursor.execute(
"CREATE UNIQUE INDEX auth_user_email_unique "
"ON auth_user (upper(email));"
)
cursor.cursor.close()
post_syncdb.connect(post_syncdb_callback, sender=app.models)
我可以
User.objects.create(username=str(random.random()), email=None)
我心中的内容。而且,
User.objects.create(username=str(random.random()), email='Foo')
User.objects.create(username=str(random.random()), email='foo')
...
IntegrityError: column email is not unique
唯一的问题是DEFAULT NULL
似乎不起作用:User.objects.create(username=str(random.random()))
使用空字符串电子邮件创建用户。
但是,在单元测试中,我相信会阻止后syncdb挂钩工作:
class DjangoUserTest(TestCase):
def test_unique_nullable_email(self):
import IPython; IPython.embed()
u1 = User.objects.create(username="u1", email=None)
u2 = User.objects.create(username="u2", email=None)
我可以进入ipython shell并看到该表已被明显修改:
In [1]: from django.db import connection
In [2]: c = connection.cursor()
In [3]: r = c.execute("select `sql` from sqlite_master WHERE tbl_name = 'auth_user';")
In [4]: r.fetchall()
Out[4]:
[(u'CREATE TABLE auth_user (\n "id" integer NOT NULL PRIMARY KEY,\n "username" varchar(30) NOT NULL UNIQUE,\n "first_name" varchar(30) NOT NULL,\n "last_name" varchar(30) NOT NULL,\n "email" varchar(75) DEFAULT NULL,\n "password" varchar(128) NOT NULL,\n "is_staff" bool NOT NULL,\n "is_active" bool NOT NULL,\n "is_superuser" bool NOT NULL,\n "last_login" datetime NOT NULL,\n "date_joined" datetime NOT NULL\n)',),
(None,),
(u'CREATE UNIQUE INDEX auth_user_email_unique ON auth_user (email COLLATE NOCASE)',)]
但是,在尝试创建时,我得到IntegrityError: auth_user.email may not be NULL
。当select sql from sqlite_master WHERE tbl_name = 'auth_user';
清楚地说"email" varchar(75) DEFAULT NULL
时,这是怎么发生的。我觉得我只需要提交post_syncdb的东西或者某事。有什么想法吗?
更新:connection.commit()
,cursor.close()
没有任何帮助,使用TransactionTestCase
无效。