Как мне сказать Django, чтобы он не создавал таблицу для поля, связанного с M2M?

Я использую эту маленькую жемчужину фрагмента кода Django для редактирования ManyToManyField в обоих направлениях:

class ManyToManyField_NoSyncdb(models.ManyToManyField):  
    def __init__(self, *args, **kwargs):  
        super(ManyToManyField_NoSyncdb, self).__init__(*args, **kwargs)
        self.creates_table = False  

class Job(models.Model):  
    persons = ManyToManyField_NoSyncdb( Person, blank=True, db_table='person_jobs' )

(детали фрагмента здесь)

Это позволяет мне выбрать всех людей на данной работе из формы рабочих мест и, наоборот, позволяет мне выбрать все рабочие места для человека из формы лиц и обновить таблицу single jobs_persons в обоих случаях.

Однако при переходе с Django 1.0 на 1.2 syncdb теперь генерирует ошибку повторяющейся таблицы, потому что create_table явно больше не поддерживается в базовом классе.

Есть ли другой способ указать Django 1.2 не создавать таблицу для RelatedField?


person jwilson2000    schedule 05.02.2011    source источник


Ответы (3)


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

Решение, которое я нашел (которое работает с Django 1.2+ и syncdb), таково:

class User(models.Model):
    groups = models.ManyToManyField('Group', through='UserGroups')

class Group(models.Model):
    users = models.ManyToManyField('User', through='UserGroups')

class UserGroups(models.Model):
    user_id = models.ForeignKey(User)
    group_id = models.ForeignKey(Group)

    class Meta:
        db_table = 'app_user_group'
        auto_created = User

См. билет 897 для получения дополнительной информации.

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

person Etienne    schedule 05.02.2011
comment
Хм. Я использую Django 1.3.1 и последовал вашему примеру (за исключением того, что мои модели находятся в разных модулях, но я не думаю, что это должно иметь значение). В любом случае, когда я делаю что-то вроде userObj.groups, я получаю сообщение об ошибке, когда Django, по-видимому, пытается использовать User как строку, а не выяснять, что это объект. Любые идеи? Спасибо. - person JamesD; 29.09.2011
comment
Не видя вашего кода, я понятия не имею. Обычно он должен работать (у меня он все еще работает в Django 1.3, 1.3.1 не проверял). Проблема может заключаться в том, что ваши модели находятся в разных модулях (я плохо помню, как работает разрешение модели, когда это строка). Вы проверили билет № 897? Есть 2 более новых решения. Последний делает то же самое, что и мой, но он довольно чистый и простой. - person Etienne; 29.09.2011

Может быть полезна «управляемая» мета-опция для моделей. Из http://docs.djangoproject.com/en/1.2/ref/models/options/#managed

Если модель с manage=False содержит ManyToManyField, указывающий на другую неуправляемую модель, промежуточная таблица для соединения «многие ко многим» также не будет создана. Однако будет создана промежуточная таблица между одной управляемой и одной неуправляемой моделью.

Если вам нужно изменить это поведение по умолчанию, создайте промежуточную таблицу как явную модель (с управляемым набором при необходимости) и используйте атрибут ManyToManyField.through, чтобы отношение использовало вашу пользовательскую модель.

person shadfc    schedule 05.02.2011

Позвольте мне опубликовать новое решение в тикете Django #897, которое также упоминает Этьен. . Он хорошо работает в Django 1.2.

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

class Test2(models.Model):
    tests1 = models.ManyToManyField(Test1, through=Test1.tests2.through, blank=True)
person Too    schedule 14.02.2012