Сохранение объекта с отношением ManyToMany - PullRequest
0 голосов
/ 09 января 2009

У меня есть модели (упрощенный пример):

class Group(models.Model):
  name = models.CharField(max_length = 32)

class Person(models.Model):
  group = models.ForeignKey(Group)

class Task(models.Model):
  group = models.ForeignKey(Group)
  people = models.ManyToManyField(Person)

  def save(self, **kwargs):
    ppl = Person.objects.all().filter(group = self.group)
    for p in ppl:
      self.people.add(p)
    super(Task, self).save(**kwargs)

Я хочу назначить задачу некоторой группе людей и добавить всех людей, которые также принадлежат к этой группе, а также некоторых других людей позже (или удалить конкретного человека из задачи). Очевидно, что сохранение не будет выполнено, потому что у объекта нет идентификатора, когда он хочет добавить объекты отношения «многие ко многим». Как справиться с такой ситуацией? Я пытался сохранить перед добавлением людей в задачу, а затем снова сохранить, но это не сработало.

С уважением
Chriss

Ответы [ 2 ]

1 голос
/ 10 января 2009

Вот как бы я это сделал. Создайте отдельную группу для каждой задачи и при необходимости инициализируйте каждую группу другой:

class Person(models.Model):
    name = models.CharField(max_length=64)

class Group(models.Model):
    name = models.CharField(max_length=32)
    people = models.ManyToManyField(Person)
    parent_group = models.ForeignKey(Group, null=True, blank=True)

    def save(self, **kwargs):
        # copy parent's people in to this group if this is a new instance and parent_group is set
        if not self.id and self.parent_group:
            for p in self.parent_group.people:
                self.people.add(p)
        super(Group, self).save(**kwargs)

class Task(models.Model):
    group = models.ForeignKey(Group)

def use_case():
    Group(name='empty group').save()

    group = Group.objects.get(name='Accounting')
    accounting_subgroup = Group(name='Accounting Copy', parent_group=group)
    accounting_subgroup.people.remove(person1)
    accounting_subgroup.people.remove(person2)
    accounting_subgroup.save()

    task = Task(group=accounting_subgroup)
    task.save()

Теперь вы можете повторно использовать свои подгруппы, плюс вы можете определить, что такое «базовые группы», такие как «Учет и продажи» и «Бухгалтерская группа 3», проверив, является ли parent_group нулевым. Однако в большинстве случаев вы не дублируете «список людей» в двух местах.

0 голосов
/ 09 января 2009

Вот пример , который не включает переопределение сохранения. Это выглядит проще, чем то, что вы делаете.

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