views:

328

answers:

2

I have models (simplified example):

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)

I want to assign the task to some group of people and add all persons who belong to that group as well, as some other people later (or remove particular person from the task). Obviously save won't be performed because object has no id when it wants to add many-to-many relationship objects. How to handle such situation? I tried saving just before adding people to task and then saving again but that didn't work.

regards
chriss

A: 

Here's an example that doesn't involve overriding save. It looks simpler than what you're doing.

S.Lott
A: 

Here's how I'd do it. Make a separate group for each task, and optionally initialize each group with another one:

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()

Now you can reuse your subgroups, plus you can determine what the "base groups" are, such as Accounting and Sales vs "Accounting team 3", by checking if parent_group is null. Mostly, though, you're not duplicating a "list of people" in two places.

Daniel