Let's say I have a Basket
model and I want to validate that no more than 5
Item
s can be added to it:
class Basket(models.Model):
items = models.ManyToManyField('Item')
def save(self, *args, **kwargs):
self.full_clean()
super(Basket, self).save(*args, **kwargs)
def clean(self):
super(Basket, self).clean()
if self.items.count() > 5:
raise ValidationError('This basket can\'t have so many items')
But when trying to save a Basket
a RuntimeError
is thrown because the maximum recursion depth is exceeded.
The error is the following:
ValueError: "<Basket: Basket>" needs to have a value for field "basket" before this many-to-many relationship can be used.
It happens in the if self.items.count() > 5:
line.
Apparently Django's intricacies simply won't allow you to validate m2m relationships when saving a model. How can I validate them then?
You can never validate relationships in the clean method of the model. This is because at clean time, the model may not yet exist, as is the case with your Basket. Something that does not exist, can also not have relationships.
You either need to do your validation on the form data as pointed out by @bhattravii, or call form.save(commit=False)
and implement a method called save_m2m
, which implements the limit.
To enforce the limit at the model level, you need to listen to the m2m_changed
signal. Note that providing feedback to the end user is a lot harder, but it does prevent overfilling the basket through different means.