【问题标题】:Django: ManyToManyField creates duplicate column nameDjango:ManyToManyField 创建重复的列名
【发布时间】: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


【解决方案1】:

如何单独创建多对多表,避免使用 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

【讨论】:

  • 这是我的第一次尝试,但你不能与抽象模型建立 ForeignKey 关系。换句话说,Resource 在这个提议的方法中不能是抽象的。
猜你喜欢
  • 2016-03-15
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 2019-01-22
  • 2020-05-25
  • 1970-01-01
  • 2017-12-02
  • 1970-01-01
相关资源
最近更新 更多