Adding elements to a ManyToMany field inside the clean() method of a model.

I am trying to automatically add a user to a ManyToMany field inside the clean() method of the Project class if a project gets added or updated:

class Project(models.Model):
    title = models.CharField(max_length=100, validators=[validate_project_title], verbose_name='Title', unique=True, null=True)
    assigned_to = models.ManyToManyField(User)
    
        
    def clean(self):
        super().save()

        project = Project.objects.get(title=self.title)

        try: # Check if the "admin" user exists in the system
            admin_user = User.objects.get(username='admin')
        except User.DoesNotExist:
            raise ValidationError('The "admin" user does not exist.')
        
        if admin_user not in project.assigned_to.all(): #adding the admin user to the users assined to the project
            project.assigned_to.add(admin_user)

But on the creation of a new model or the update of an existing model only the users choosen in the gui are added to the object. (The code runs without prompting any errrors. )

Hello @marc406 !

Here are some things you might want to consider:

The clean() method is generally used for data validation in preparation for saving a model. You must not call the save() method here.

For checking whether an instance exists in the database, it’s better to use the exists() method on a Queryset.

class Project(models.Model):
    title = models.CharField(max_length=255, validators=[validate_project_title], verbose_name='Title', unique=True, null=True)
    assigned_to = models.ManyToManyField(User)

    def clean(self):
        super().clean() # Call the superclass clean method

        # Check if "admin" user exists using exists
        if not User.objects.filter(username='admin').exists():
            raise ValidationError('The "admin" user does not exist.')

    def save(self, *args, **kwargs):
        # Call superclass save method to save the object
        super().save(*args, **kwargs)

        # Ensure "admin" user is assigned to the project here
        admin_user = User.objects.get(username='admin')
        if admin_user not in self.assigned_to.all():
            self.assigned_to.add(admin_user)

Note however that the clean() method is not automatically called when you save a model instance. You will have to call it yourself before saving.

Welcome @marc406 !

In addition to the above:

There’s no need to issue this query. This is the clean method of this instance of Project. You can refer to the current object as self.

Also, according to the docs at Many-to-many relationships | Django documentation | Django, you don’t need to check for existance of a relationship. By default, Django will not create duplicate entries.

That means that this:

would more appropriately be:

self.assigned_to.add(admin_user)
1 Like