Django:ManyToManyField创建重复的列名

时间:2011-12-20 21:13:12

标签: django django-models

我的应用程序中有两种类型的用户: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创建的命名冲突?

1 个答案:

答案 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