Джанго копия поля многие ко многим - PullRequest
4 голосов
/ 07 августа 2011

У меня есть модель Django с 2 полями «многие ко многим». Когда модель сохраняется из интерфейса администратора, мне нужно проверить, если второе поле пустое, а если оно пустое, то мне нужно, чтобы элементы из первого поля были скопированы во второе. Как я могу это сделать?

UPDATE

Ответ Мэтью кажется, что он будет работать отлично, но я не могу сохранить экземпляр после того, как скопировал поле. Я пробовал instance.save () безуспешно.

Ответы [ 4 ]

3 голосов
/ 07 августа 2011

Вы можете использовать сигнал после сохранения.Похоже, что это может быть лучшим способом справиться с вашими потребностями: бонус в том, что он будет работать и вне администратора.

@models.signals.post_save(sender=MyModel)
def duplicate_missing_field(sender, instance, **kwargs):
    if not instance.my_second_m2m.count():
        instance.my_second_m2m.add(*instance.my_first_m2m.all())
        # or *instance.my_first_m2m.values_list('pk', flat=True), I think

Мой код может быть не совсем правильным:читать по сигналам в Django.

3 голосов
/ 10 августа 2011

Используемый сигнал - это не post_save, а m2m_changed, который отправляется через много после сохранения модели в базе данных.

@models.signals.m2m_changed(sender=MyModel.second_m2m.through)
def duplicate_other_on_this_if_empty(sender, instance, action, reverse, model, pk_set, **kwargs):
    # just before adding a possibly empty set in "second_m2m", check and populate.
    if action == 'pre_add' and not pk_set:
        instance.__was_empty = True
        pk_set.update(instance.first_m2m.values_list('pk', flat=True))

@models.signals.m2m_changed(sender=MyModel.first_m2m.through)
def duplicate_this_on_other_if_empty(sender, instance, action, reverse, model, pk_set, **kwargs):
    # Just in case the "first_m2m" signals are sent after the other
    # so the actual "population" of the "second_m2m" is wrong:
    if action == 'post_add' and not pk_set and getattr(instance, '__was_empty'):
        instance.second_m2m = list(pk_set)
        delattr(instance, '__was_empty')

Редактировать: следующий код прощеи на основе новых знаний об определении моделей

В вашем коде сигналы 'first_m2m' отправляются перед 'second_m2m' (это действительно зависит от определения вашей модели).Таким образом, мы можем работать в предположении, что когда сигналы 'second_m2m' получены, 'first_m2m' уже заполнен текущими данными.

Это делает нас счастливее, потому что теперь вам нужно только проверить m2m-pre-адд:

@models.signals.m2m_changed(sender=MyModel.second_m2m.through)
def duplicate_other_on_this_if_empty(sender, instance, action, reverse, model, pk_set, **kwargs):
    # just before adding a possibly empty set in "second_m2m", check and populate.
    if action == 'pre_add' and not pk_set:
        pk_set.update(instance.first_m2m.values_list('pk', flat=True))
0 голосов
/ 13 августа 2011

Здесь вы можете увидеть определение переопределения сохранения администратора , просто переопределите его и проверьте, пусто ли связанное поле, если это так, сохраните объект, получите связанные данные со второго M2M и установите егопервый M2M и сохраните его снова ...

0 голосов
/ 07 августа 2011

Вы можете переопределить метод clean, чтобы выполнить дополнительную проверку, поэтому, если второе many2many пустое, вы можете установить значения по умолчанию, например:

def clean(self):
    super(MyClassModel, self).clean()

    if not self.MySecondMany2Many:
        # fill data

, вы должны установить этот код в вашем models.pyвнутри вашего класса.Если очистка не работает, потому что модель должна быть сохранена, вы также можете переопределить функцию сохранения, это та же самая процедура.

Я не проверял это, и я не думаю, что вы можете проверить, является ли поле many2many пустым, но вы должны понять это :)

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