我的应用程序中有两种类型的用户: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创建的命名冲突?
答案 0 :(得分:0)
如何分别创建多对多表,避免使用ManyToMany字段?您可以使用管理器或方法返回给定资源的用户列表,反之亦然。
class Resource(models.Model):
...
class Meta:
abstract = True
def owners(self):
return ResourceOwner.objects.filter(resource=self)
class ResourceOwners(models.Model):
resource = models.ForeignKey(Resource)
owner = models.ForeignKey(User)
class Meta:
abstract = True