Django双向ManyToMany - 如何防止在第二个模型上创建表?

时间:2011-02-03 00:34:40

标签: python django many-to-many

我有两个模型,每个模型都有一个共享的ManyToMany,使用db_table字段。但是,对于第二个模型,如何阻止syncdb尝试创建共享表?

class Model1(models.Model):
    othermodels = ManyToManyField('Model2', db_table='model1_model2', related_name='model1_model2')

class Model2(models.model):
    othermodels = ManyToManyField('Model1', db_table='model1_model2', related_name='model2_model1')

它在我的开发环境中工作得很好,因为有些表是零碎地创建的,因为我把它全部建成了。但是从一个空数据库中,syncdb抛出:     _mysql_exceptions.OperationalError:(1050,“表'model1_model2'已存在”)

我是否在第二个模型的字段中缺少一个标志以防止重复创建表?或者我只是完全错了?

4 个答案:

答案 0 :(得分:19)

我也找到了这个解决方案,对我来说非常有用:

class Test1(models.Model):
    tests2 = models.ManyToManyField('Test2', blank=True)

class Test2(models.Model):
    tests1 = models.ManyToManyField('Test1', through=Test1.tests2.through, blank=True)

答案 1 :(得分:5)

您无需在关系的两侧放置ManyToManyFieldDjango will do that for you

你可能想要更像这样的东西:

class Model1(models.Model):
    name = models.CharField(max_length=128)
    ...

class Model2(models.Model):
    name = models.CharField(max_length=128)
    othermodels = models.ManyToManyField(Model1, through='Model1Model2')
    ...        

class Membership(models.Model):
    class Meta:
        db_table = 'model1_model2'
    model1 = models.ForeignKey(Model1)        
    model2 = models.ForeignKey(Model2)

当您使用模型时,Model1的实例将有一个othermodels_set字段,该字段由django自动添加。 Model2的实例将othermodels

答案 2 :(得分:2)

class Awesome(models.Model):
 one = models.TextField()
 class Meta:
  # Prevent table creation. 
  abstract = True

http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes

这不是你想要的,但它是我所相信的最接近的。提出观点会不简单?

也许:

class Awesome(models.Model):
  one = models.CharField(max_length = 255)
  two = models.CharField(max_length = 255)

class AwesomeOne(Awesome):
  fieldOne = models.ForeignKey(User, related_name = 'one')
  class Meta:
   abstract = True
class AwesomeTwo(Awesome):
  fieldTwo = models.ForeignKey(User, related_name = 'two')
  class Meta:
   abstract = True

然后,您可以创建一个表并覆盖__getattr__以阻止对原始字段的访问。

答案 3 :(得分:1)

在Django中,ManyToMany默认是双向的。我们认为你只需要在一个模型上定义它,而不是在两个模型上定义它(通常你不需要给表格命名):

class Model1(models.Model):
    othermodels = ManyToManyField('Model2')

class Model2(models.model):
    ...

就是这样。现在syncdb会很开心。有关详细信息:Django docs

唯一的缺点是,如果您使用管理员,则只能在othermodels中访问Model1

修改

因此,如果您想要在Admin中的两个模型中访问ManyToMany,那么官方解决方案是使用inlinemodel作为第二个模型。几天前我也有同样的问题/需要。我对 inlinemodel 解决方案并不满意(如果你有很多条目,不能使用* filter_horizo​​ntal *小部件等,那么DB查询会很重要。)

我找到的解决方案(使用Django 1.2+和syncdb)是这样的:

class Model1(models.Model):
    othermodels = models.ManyToManyField('Model2', through='Model1Model2')

class Model2(models.Model):
    othermodels = models.ManyToManyField('Model1', through='Model1Model2')

class Model1Model2(models.Model):
    model1 = models.ForeignKey(Model1)
    model2 = models.ForeignKey(Model2)

    class Meta:
        db_table = 'app_model1_model2'
        auto_created = Model1

有关详情,请参阅票证897

不幸的是,如果您使用South,则必须在自动创建的每个迁移文件中删除app_model1_model2表的创建。