Django Двунаправленный ManyToMany - Как предотвратить создание таблицы на второй модели? - PullRequest
13 голосов
/ 03 февраля 2011

У меня есть две модели, каждая из которых имеет общий 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 ]

20 голосов
/ 18 февраля 2012

Я также нашел это решение, которое отлично сработало для меня:

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

class Test2(models.Model):
    tests1 = models.ManyToManyField('Test1', through=Test1.tests2.through, blank=True)
5 голосов
/ 03 февраля 2011

Вам не нужно ставить ManyToManyField с обеих сторон отношения. Django сделает это за вас .

Возможно, вы захотите что-то похожее на это:

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 голосов
/ 03 февраля 2011
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__, чтобы заблокировать доступ к исходным полям.

1 голос
/ 03 февраля 2011

В Django ManyToMany являются двунаправленными по умолчанию.Смысл в том, что вам нужно определить его только для одной модели, а не для обеих (и обычно вам не нужно давать имя таблице):

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

class Model2(models.model):
    ...

Вот и все.Теперь syncdb будет счастлив.Для получения дополнительной информации: Django docs

Единственным недостатком является то, что если вы используете администратора, у вас будет доступ к othermodels только в Model1.

Редактировать

Итак, если вы хотите иметь доступ к ManyToMany в обеих моделях в Admin, в настоящее время официальное решение заключается в использовании inlinemodel для второй модели.У меня была такая же проблема / необходимость всего несколько дней назад.И я не очень доволен решением inlinemodel (интенсивно в запросах к БД, если у вас много записей, невозможно использовать виджет * filter_hor Horizontal * и т. Д.).

Решение Iнайдено (это работает с 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 для получения дополнительной информации.

К сожалению, если выиспользуя Юг , вам придется удалить создание таблицы app_model1_model2 в каждом автоматически создаваемом файле миграции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...