Bayon Sharke
Bayon Sharke

Reputation: 71

Django Populate ManyToManyField overriding save method

When i create a Mess also it requires to fill the admin field and i do it always.

I want, when i create a Mess, the members field of the mess should populate automatically with the admin

Here you go for my admin:

class Mess(models.Model):
    alias = models.UUIDField(
        primary_key=True,
        default=uuid4,
        editable=False
    )
    name = models.CharField(max_length=50, null=False, blank=False)
    address = models.CharField(max_length=300)
    admin = models.OneToOneField(
        Person,
        on_delete=models.CASCADE,
        related_name='mess_admin'
    )
    members = models.ManyToManyField(
        Person,
        related_name='mess_members',
        blank=True,
    )

    def save(self, *args, **kwargs):
        if self.admin not in self.members_set.all():
            self.members.add(self.admin)
        super(Mess, self).save(*args, **kwargs)

I want overriding save method, I want to add the admin to members field too but I don't to populate it manually, it will add the admin of the mess and the same admin will be in members field too.

Can anyone help me to achive this? My current save method is not working following my requirement.

this is the errors it throws:

AttributeError at /admin/mess/mess/add/
'Mess' object has no attribute 'members_set'

Upvotes: 1

Views: 265

Answers (2)

Moi
Moi

Reputation: 379

class Mess(models.Model):
    ...
    admin = models.OneToOneField(
        Person,
        on_delete=models.CASCADE,
        related_name='mess_admin'
    )
    members = models.ManyToManyField(
        Person,
        related_name='mess_members',
        blank=True,
    )

    def save(self, *args, **kwargs):
        super(Mess, self).save(*args, **kwargs)
        if self.members.filter(pk=self.admin.id).count() == 0:
            self.members.add(self.admin)

should do the trick.

Explanation: 1) As mentioned by @Ralf, you have the property members and not members_set. 2) Save first, then see if your model still needs an update

Upvotes: 1

Ralf
Ralf

Reputation: 16515

In your model you define the field as members, not members_set:

class Mess(models.Model):
    ...
    members = models.ManyToManyField(...)
    ...

I also suggest using .filter() and .exists() instead of not in to test for membership:

def save(self, *args, **kwargs):
    if not self.members.filter(pk=self.admin.pk).exists():
    ...

Have you tried saving first and then adding to members? In that case the call to super() comes first:

def save(self, *args, **kwargs):
    super().save(*args, **kwargs)

    if not self.members.filter(pk=self.admin.pk).exists():
        self.members.add(self.admin)

Upvotes: 1

Related Questions