【发布时间】:2011-12-20 21:13:12
【问题描述】:
我的应用程序中有两种类型的用户:auth.User,来自 django.contrib.auth(标准 Django 身份验证模块)和mysql.User,在我自己的模块中。此外,mysql.User 继承自一个抽象模型。整个事情看起来与此类似(为简洁起见,省略了一些字段):
class Resource(Model):
class Meta:
abstract = True
owners = ManyToManyField('auth.User', related_name='%(class)s_owners')
class User(Resource):
name = CharField(max_length=16)
host = CharField(max_length=64)
class Database(Resource):
name = CharField(max_length=64)
如您所见,我想让多个auth.Users 可以“拥有”一个给定的mysql.User 和一个给定的mysql.Database,因此是ManyToManyFields。但是,当我运行 ./manage.py syncdb 时,我得到了错误:
_mysql_exceptions.OperationalError: (1060, "Duplicate column name 'user_id'")
确实,./manage.py sql mysql 显示了错误的来源(再次,为简洁起见,省略了一些列和 ALTER TABLE 语句):
CREATE TABLE `mysql_database` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(64) NOT NULL,
UNIQUE (`server_id`, `name`)
);
CREATE TABLE `mysql_user` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(16) NOT NULL,
`host` varchar(64) NOT NULL,
UNIQUE (`server_id`, `name`, `host`)
);
CREATE TABLE `mysql_database_owners` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`database_id` integer NOT NULL,
`user_id` integer NOT NULL,
UNIQUE (`database_id`, `user_id`)
);
CREATE TABLE `mysql_user_owners` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`user_id` integer NOT NULL,
`user_id` integer NOT NULL, -- <<<<< here is the conflict >>>>>
UNIQUE (`user_id`, `user_id`)
);
请注意如何创建 Database 的中间表而没有命名冲突,但 User 的表有冲突。我没有看到 ManyToManyField 提供了一种在中间表中提供列名的方法,但不幸的是我认为这就是我需要的。
我尝试的另一种方法是显式创建中间表并使用 ManyToManyField 的through 选项,如下所示:
class Resource(models.Model):
class Meta:
abstract = True
owners = models.ManyToManyField('auth.User', related_name='%(class)s_owners', through='Owner')
class Owner(models.Model):
user = models.ForeignKey('auth.User', related_name='Resource_owners')
resource = models.ForeignKey(Resource)
然后我得到这个错误:
AssertionError: ForeignKey cannot define a relation with abstract class Resource
这是 Django 所期望的。
那么,除了将mysql.User 重命名为mysql.DBUser 之类的名称之外,有什么办法可以避免 Django 造成的命名冲突吗?
【问题讨论】:
-
我猜你不想在用户和数据库上分别定义所有者 M2M 关系,并为用户-用户关系指定直通表;因此失去了抽象的优势(尽管也许你可以在资源上定义一个“所有者”属性)。另一个(疯狂的)想法:将“通过”设置为 '%(class)Owner' 并定义两个 M2M 模型:UserOwner 和 DatabaseOwner。不过,我真的认为它不起作用......
标签: django django-models