Django设置存储引擎和默认字符集

9
从我的models.py创建我的表。我不知道如何做两件事-
  1. 我想指定MySQL将我的一些表创建为InnoDB,而将另一些表创建为MyISAM。我该怎么做?
  2. 此外,我想将我的表的DEFAULT CHARSET指定为utf8。我该怎么做?
当我运行syncdb时,我看到的是这样的-
...
) ENGINE=MyISAM DEFAULT CHARSET=latin1

我使用Ubuntu 10.04,Django 1.2.X和MySQL 5.1.X。
更新: 我认为这些可能是MySQL的默认设置,所以我最终更改了my.cnf文件,在其中添加了default-character-set = utf8。但是没有用。
2个回答

18

我认为您不能逐个表更改存储引擎,但可以在按数据库进行更改。 当然,这意味着例如InnoDB外键约束无法应用于对MyISAM表的外键。

因此,您需要声明两个“数据库”,这两个数据库可能在同一服务器上:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        #...
    }
    'innodb': {
        'ENGINE': 'django.db.backends.mysql',
        #...
        'OPTIONS': { 'init_command': 'SET storage_engine=INNODB;' }
    }
}

你只需要在针对InnoDB的表的查询集上应用using('innodb')即可。

至于UTF-8,我认为你需要在数据库级别上进行操作。我觉得syncdb只会为你创建表而不是数据库。你应该手动创建数据库,这样在运行syncdb之前就可以设置正确的权限。你需要使用以下命令来创建数据库:

CREATE DATABASE django CHARACTER SET utf8;

尽管如此,我通常建议用户在数据库中创建两个Django用户:一个用于数据库架构工作(“admin”),另一个用于其他所有事情(具有不同的密码):

CREATE DATABASE django CHARACTER SET utf8;
CREATE USER 'django_site'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE ON django.* TO django_site;
CREATE USER 'django_admin'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE ON django.* TO django_admin;
GRANT CREATE, DROP, ALTER, INDEX, LOCK TABLES ON django.* TO django_admin;
FLUSH PRIVILEGES;

(请注意,这需要对每个数据库执行。)

要使此功能生效,您需要修改manage.py

import sys
if len(sys.argv) >= 2 and sys.argv[1] in ["syncdb", "dbshell", "migrate"]:
    os.environ['DJANGO_ACCESS'] = "ADMIN"

然后在你的settings.py中,使用环境变量来选择正确的设置。确保站点(即非管理员)用户是默认的。

(另外,我不在settings.py中存储数据库设置、SECRET_KEY或任何其他敏感信息,因为我的Django项目存储在Mercurial中;我让settings.py从一个仅由Django用户和服务器管理员可以访问的外部文件中提取所有这些内容。至于如何实现,请留给读者自行探讨...因为我已经在回答其他人的问题时详细说明了一些,而且现在懒得再去查了。)


3
好的,你可以在一个数据库中混合使用InnoDB和MyISAM。我通过困难的方式学习到,当一些外键被强制执行时,有些外键却没有被强制执行。因此,将MySQL默认表类型设置为InnoDB是一个好主意。否则,即使你忘记了导出这个信息,转储和重新加载也可能会改变表类型。 - Tomasz Zieliński
请问您能解释一下 using('innodb') 是什么意思以及应该在哪里添加吗? - nizam.sp
默认情况下,QuerySet 使用 settings.DATABASES['default'] 中指定的数据库。如果要使用不同的数据库(例如上面示例中命名为 'innodb' 的数据库),则需要在 QuerySet 上调用 using 函数(例如 Foo.objects.filter(...).using('innodb'))。 - Mike DeSimone

2
CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(32) NOT NULL,
  `lastname` varchar(32) NOT NULL,
  `gender` varchar(6) NOT NULL,
  `email` varchar(32) NOT NULL,
  `username` varchar(32) NOT NULL,
  `password` varchar(32) NOT NULL,
  `created` datetime NOT NULL,
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=76 ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接