Подтвердить что ты не робот

Django Bi-directional 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')

Он отлично работает в моей среде dev, потому что некоторые из таблиц создаются по частям, поскольку я все это создал. Но из пустой базы данных syncdb выбрасывает:   _mysql_exceptions.OperationalError: (1050, "Таблица" model1_model2 "уже существует" )

Есть ли флаг, отсутствующий во втором поле модели, чтобы предотвратить создание дубликатов таблиц? Или я просто делаю это совершенно неправильно?

4b9b3361

Ответ 1

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

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

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

Ответ 2

Вам не нужно ставить 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.

Ответ 3

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

Ответ 4

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

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

class Model2(models.model):
    ...

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

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

Изменить

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

Решение, которое я нашел (работая с 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 в каждом созданном файле миграции автоматически.