2013-09-20 3 views
0

У меня есть две модели Django, связанные через ManyToManyField:Удалить связанные модели в Джанго через ManyToManyField

class Board(models.Model): 
    name = models.CharField(max_length=100, blank=False) 

class Card(models.Model): 
    title = models.CharField(max_length=100, blank=False) 
    boards = models.ManyToManyField(Board) 

Как вы можете видеть, Card может появиться в нескольких Board с. Алгоритм Я хотел бы написать следующим образом:

  1. Если удалить все Card сек в Board, это нормально. Board остается пустым, и все.
  2. Если я удалю Board, все Cards, которые не прикреплены к другому Board, должны быть удалены.

Моей первая идея заключается в том переопределение pre_delete сигнала на Board, но я не уверен, что это лучший способ сделать это.

ответ

1

Вы можете сделать это на доске .delete(). Что-то вроде этого:

def delete(*args, **kwargs): 
    self.card_set.annotate(board_count=Count('boards')).filter(board_count=1).delete() 
    super(Board, self).delete(*args, **kwargs) 

Это будет выбирать все доски, связанные карты, а затем отфильтровать из карт, которые связаны с более чем одной доски. (Вы уже знаете, что одна из плат - текущая плата), а затем удалите их.

Также важно помнить, что это будет вызываться только при звонке .delete() на одной плате. Не на запросе.

EDIT: поскольку .delete() не вызывается при вызове .delete() на множестве запросов, я думаю, что pre_delete сигнал был бы лучшим выбором:

@receiver(pre_delete, sender=Board) 
def delete_associated_cards(sender, instance, using, **kwargs): 
    instance.card_set.annotate(board_count=Count('boards')).filter(board_count=1).delete() 
+0

[В документации Django] [1] он говорит: Обратите внимание, что метод delete() для объекта не обязательно вызывается при удалении объектов в массе с помощью QuerySet. Чтобы обеспечить выполнение индивидуальной логики удаления, вы можете использовать сигналы pre_delete и/или post_delete. [1]: https://docs.djangoproject.com/en/1.5/topics/db/models/#overriding-predefined-model-methods –

+0

Вы правы. Извините, я думал о 'pre_save' и' post_save'. В этом случае вы должны использовать 'pre_delete'. Но тот же код должен работать - просто переместите его в' pre_save' – jproffitt

+0

. Я отредактировал свой ответ, чтобы вместо этого использовать 'pre_delete'. – jproffitt

Смежные вопросы